You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2017/06/02 23:59:48 UTC

[1/2] incubator-juneau git commit: Enhanced serializer and parser listener API.

Repository: incubator-juneau
Updated Branches:
  refs/heads/master 3551f4c9c -> 0ccac121d


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
index df35f9a..db65a96 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
@@ -364,7 +364,7 @@ public class UrlEncodingSerializer extends UonSerializer implements PartSerializ
 			Object value = p.getValue();
 			Throwable t = p.getThrown();
 			if (t != null)
-				session.addBeanGetterWarning(pMeta, t);
+				session.onBeanGetterException(pMeta, t);
 
 			if (session.canIgnoreValue(cMeta, key, value))
 				continue;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
index e7ff61e..5fee28f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
@@ -16,6 +16,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.serializer.*;
 import org.apache.juneau.uon.*;
 
 /**
@@ -266,6 +267,12 @@ public class UrlEncodingSerializerBuilder extends UonSerializerBuilder {
 		return this;
 	}
 
+	@Override /* SerializerBuilder */
+	public UrlEncodingSerializerBuilder listener(Class<? extends SerializerListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public UrlEncodingSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
index f4a4559..f1d24d2 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
@@ -282,7 +282,7 @@ public class XmlParser extends ReaderParser {
 					xmlMeta.getAttrsProperty().add(m, key, key, val);
 				} else {
 					Location l = r.getLocation();
-					onUnknownProperty(session, key, m, l.getLineNumber(), l.getColumnNumber());
+					session.onUnknownProperty(key, m, l.getLineNumber(), l.getColumnNumber());
 				}
 			} else {
 				bpm.set(m, key, val);
@@ -361,7 +361,7 @@ public class XmlParser extends ReaderParser {
 					BeanPropertyMeta pMeta = xmlMeta.getPropertyMeta(currAttr);
 					if (pMeta == null) {
 						Location loc = r.getLocation();
-						onUnknownProperty(session, currAttr, m, loc.getLineNumber(), loc.getColumnNumber());
+						session.onUnknownProperty(currAttr, m, loc.getLineNumber(), loc.getColumnNumber());
 						skipCurrentTag(r);
 					} else {
 						session.setCurrentProperty(pMeta);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
index 2f48757..fcde50e 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
@@ -237,6 +237,12 @@ public class XmlParserBuilder extends ParserBuilder {
 		return this;
 	}
 
+	@Override /* ParserBuilder */
+	public XmlParserBuilder listener(Class<? extends ParserListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public XmlParserBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
index 9e24414..37e7061 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
@@ -16,6 +16,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.serializer.*;
 
 /**
  * Builder class for building instances of XML Schema serializers.
@@ -203,6 +204,12 @@ public class XmlSchemaSerializerBuilder extends XmlSerializerBuilder {
 		return this;
 	}
 
+	@Override /* SerializerBuilder */
+	public XmlSchemaSerializerBuilder listener(Class<? extends SerializerListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public XmlSchemaSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
index af5ce51..4bee6b4 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
@@ -637,7 +637,7 @@ public class XmlSerializer extends WriterSerializer {
 				Object value = p.getValue();
 				Throwable t = p.getThrown();
 				if (t != null)
-					session.addBeanGetterWarning(pMeta, t);
+					session.onBeanGetterException(pMeta, t);
 
 				if (session.canIgnoreValue(cMeta, key, value))
 					continue;
@@ -654,7 +654,7 @@ public class XmlSerializer extends WriterSerializer {
 							Object value2 = p2.getValue();
 							Throwable t2 = p2.getThrown();
 							if (t2 != null)
-								session.addBeanGetterWarning(pMeta, t);
+								session.onBeanGetterException(pMeta, t);
 							out.attr(ns, key2, value2);
 						}
 					} else /* Map */ {
@@ -697,7 +697,7 @@ public class XmlSerializer extends WriterSerializer {
 				Object value = p.getValue();
 				Throwable t = p.getThrown();
 				if (t != null)
-					session.addBeanGetterWarning(pMeta, t);
+					session.onBeanGetterException(pMeta, t);
 
 				if (session.canIgnoreValue(cMeta, key, value))
 					continue;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
index 2e812b9..339904b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
@@ -350,6 +350,12 @@ public class XmlSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
+	@Override /* SerializerBuilder */
+	public XmlSerializerBuilder listener(Class<? extends SerializerListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public XmlSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/javadoc/overview.html b/juneau-core/src/main/javadoc/overview.html
index 477c103..9488d20 100644
--- a/juneau-core/src/main/javadoc/overview.html
+++ b/juneau-core/src/main/javadoc/overview.html
@@ -6237,6 +6237,21 @@
 			<li><jsf>URLENC_paramFormat</jsf> has been moved to {@link org.apache.juneau.uon.UonSerializerContext#UON_paramFormat}, 
 				and the UON/URL-Encoding serializers will now always serialize all values as plain text.
 				<br>This means that arrays and maps are converted to simple comma-delimited lists.
+			<li>Listener APIs added to serializers and parsers:
+				<ul>
+					<li>{@link org.apache.juneau.serializer.SerializerListener}
+					<li>{@link org.apache.juneau.serializer.SerializerBuilder#listener(Class)}
+					<li>{@link org.apache.juneau.rest.annotation.RestResource#serializerListener()}
+					<li>{@link org.apache.juneau.rest.RestConfig#serializerListener(Class)}
+					<li>{@link org.apache.juneau.parser.ParserListener}
+					<li>{@link org.apache.juneau.parser.ParserBuilder#listener(Class)}
+					<li>{@link org.apache.juneau.rest.annotation.RestResource#parserListener()}
+					<li>{@link org.apache.juneau.rest.RestConfig#parserListener(Class)}
+					<li>{@link org.apache.juneau.rest.client.RestClientBuilder#listeners(Class,Class)}
+				</ul>
+			<li>The {@link org.apache.juneau.BeanContext#BEAN_debug} flag will now capture parser input and make it
+				available through the {@link org.apache.juneau.parser.ParserSession#getInputAsString()} method so that it can be used
+				in the listeners.
 		</ul>
 
 		<h6 class='topic'>org.apache.juneau.rest</h6>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
index 65b4dc8..93e7a3c 100644
--- a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
+++ b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
@@ -1045,6 +1045,21 @@ public class RestClientBuilder extends CoreObjectBuilder {
 	}
 
 	/**
+	 * Sets the {@link SerializerContext#SERIALIZER_listener} and {@link ParserContext#PARSER_listener} property on all
+	 * 	serializers and parsers in this group.
+	 *
+	 * @param sl The new serializer listener.
+	 * @param pl The new parser listener.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_abridged
+	 */
+	public RestClientBuilder listeners(Class<? extends SerializerListener> sl, Class<? extends ParserListener> pl) {
+		property(SERIALIZER_listener, sl);
+		property(PARSER_listener, pl);
+		return this;
+	}
+
+	/**
 	 * Sets the {@link ParserContext#PARSER_trimStrings} property on all parsers in this group.
 	 *
 	 * @param value The new value for this property.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
index 3df4fea..8576e18 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestConfig.java
@@ -86,6 +86,8 @@ public class RestConfig implements ServletConfig {
 		beanFilters = new ArrayList<Class<?>>(),
 		pojoSwaps = new ArrayList<Class<?>>(),
 		paramResolvers = new ArrayList<Class<?>>();
+	Class<? extends SerializerListener> serializerListener;
+	Class<? extends ParserListener> parserListener;
 	SerializerGroupBuilder serializers = new SerializerGroupBuilder();
 	ParserGroupBuilder parsers = new ParserGroupBuilder();
 	EncoderGroupBuilder encoders = new EncoderGroupBuilder().append(IdentityEncoder.INSTANCE);
@@ -177,6 +179,8 @@ public class RestConfig implements ServletConfig {
 				addBeanFilters(r.beanFilters());
 				addPojoSwaps(r.pojoSwaps());
 				addParamResolvers(r.paramResolvers());
+				serializerListener(r.serializerListener());
+				parserListener(r.parserListener());
 				if (! r.stylesheet().isEmpty())
 					setStyleSheet(c, r.stylesheet());
 				if (! r.favicon().isEmpty())
@@ -355,6 +359,34 @@ public class RestConfig implements ServletConfig {
 	}
 
 	/**
+	 * Specifies the serializer listener class to use for listening to non-fatal serialization errors.
+	 * <p>
+	 * This is the programmatic equivalent to the {@link RestResource#serializerListener() @RestResource.serializerListener()} annotation.
+	 *
+	 * @param listener The listener to add to this config.
+	 * @return This object (for method chaining).
+	 */
+	public RestConfig serializerListener(Class<? extends SerializerListener> listener) {
+		if (listener != SerializerListener.class)
+			this.serializerListener = listener;
+		return this;
+	}
+
+	/**
+	 * Specifies the parser listener class to use for listening to non-fatal parse errors.
+	 * <p>
+	 * This is the programmatic equivalent to the {@link RestResource#parserListener() @RestResource.parserListener()} annotation.
+	 *
+	 * @param listener The listener to add to this config.
+	 * @return This object (for method chaining).
+	 */
+	public RestConfig parserListener(Class<? extends ParserListener> listener) {
+		if (listener != ParserListener.class)
+			this.parserListener = listener;
+		return this;
+	}
+
+	/**
 	 * Adds class-level parameter resolvers to this resource.
 	 * <p>
 	 * This is the programmatic equivalent to the {@link RestResource#paramResolvers() @RestResource.paramResolvers()} annotation.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
index 1fd1523..779a1e4 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -639,8 +639,8 @@ public final class RestContext extends Context {
 
 			ps.addBeanFilters(beanFilters).addPojoSwaps(pojoSwaps).setProperties(properties);
 
-			serializers = sc.serializers.beanFilters(beanFilters).pojoSwaps(pojoSwaps).properties(properties).build();
-			parsers = sc.parsers.beanFilters(beanFilters).pojoSwaps(pojoSwaps).properties(properties).build();
+			serializers = sc.serializers.beanFilters(beanFilters).pojoSwaps(pojoSwaps).properties(properties).listener(sc.serializerListener).build();
+			parsers = sc.parsers.beanFilters(beanFilters).pojoSwaps(pojoSwaps).properties(properties).listener(sc.parserListener).build();
 			urlEncodingSerializer = new UrlEncodingSerializer(ps);
 			urlEncodingParser = new UrlEncodingParser(ps);
 			encoders = sc.encoders.build();

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestResource.java b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
index 52cfa07..5e86742 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
@@ -830,4 +830,14 @@ public @interface RestResource {
 	 * The programmatic equivalent to this annotation are the {@link RestConfig#setPageLinks(String)}/{@link RestResponse#setPageLinks(Object)} methods.
 	 */
 	String pageLinks() default "";
+
+	/**
+	 * Specifies the serializer listener class to use for listening for non-fatal errors.
+	 */
+	Class<? extends SerializerListener> serializerListener() default SerializerListener.class;
+
+	/**
+	 * Specifies the parser listener class to use for listening for non-fatal errors.
+	 */
+	Class<? extends ParserListener> parserListener() default ParserListener.class;
 }


[2/2] incubator-juneau git commit: Enhanced serializer and parser listener API.

Posted by ja...@apache.org.
Enhanced serializer and parser listener API.

Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/0ccac121
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/0ccac121
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/0ccac121

Branch: refs/heads/master
Commit: 0ccac121d19b55171c1c9910cb088b2b933d20d7
Parents: 3551f4c
Author: JamesBognar <ja...@apache.org>
Authored: Fri Jun 2 19:59:43 2017 -0400
Committer: JamesBognar <ja...@apache.org>
Committed: Fri Jun 2 19:59:43 2017 -0400

----------------------------------------------------------------------
 .../java/org/apache/juneau/jena/RdfParser.java  |  2 +-
 .../apache/juneau/jena/RdfParserBuilder.java    |  6 ++
 .../org/apache/juneau/jena/RdfSerializer.java   |  2 +-
 .../juneau/jena/RdfSerializerBuilder.java       |  6 ++
 .../apache/juneau/html/CommonParserTest.java    | 23 +++--
 .../apache/juneau/jena/CommonParserTest.java    | 24 ++---
 .../apache/juneau/json/CommonParserTest.java    | 24 ++---
 .../urlencoding/CommonParser_UonTest.java       | 24 ++---
 .../CommonParser_UrlEncodingTest.java           | 24 ++---
 .../org/apache/juneau/xml/CommonParserTest.java | 24 ++---
 .../main/java/org/apache/juneau/Session.java    |  8 +-
 .../org/apache/juneau/csv/CsvParserBuilder.java |  6 ++
 .../apache/juneau/csv/CsvSerializerBuilder.java |  6 ++
 .../juneau/encoders/EncoderGroupBuilder.java    |  1 +
 .../java/org/apache/juneau/html/HtmlParser.java |  2 +-
 .../apache/juneau/html/HtmlParserBuilder.java   |  7 ++
 .../org/apache/juneau/html/HtmlSerializer.java  |  6 +-
 .../juneau/html/HtmlSerializerBuilder.java      |  7 ++
 .../apache/juneau/ini/ConfigFileBuilder.java    |  1 +
 .../org/apache/juneau/internal/ClassUtils.java  | 20 ++++
 .../org/apache/juneau/internal/StringUtils.java |  1 -
 .../org/apache/juneau/jso/JsoParserBuilder.java |  6 ++
 .../apache/juneau/jso/JsoSerializerBuilder.java |  6 ++
 .../java/org/apache/juneau/json/JsonParser.java |  2 +-
 .../apache/juneau/json/JsonParserBuilder.java   |  6 ++
 .../json/JsonSchemaSerializerBuilder.java       |  7 ++
 .../org/apache/juneau/json/JsonSerializer.java  |  2 +-
 .../juneau/json/JsonSerializerBuilder.java      |  6 ++
 .../apache/juneau/msgpack/MsgPackParser.java    |  2 +-
 .../juneau/msgpack/MsgPackParserBuilder.java    |  6 ++
 .../juneau/msgpack/MsgPackSerializer.java       |  2 +-
 .../msgpack/MsgPackSerializerBuilder.java       |  6 ++
 .../java/org/apache/juneau/parser/Parser.java   | 44 ---------
 .../org/apache/juneau/parser/ParserBuilder.java | 20 ++++
 .../org/apache/juneau/parser/ParserContext.java | 17 ++++
 .../juneau/parser/ParserGroupBuilder.java       | 11 +++
 .../apache/juneau/parser/ParserListener.java    | 26 +++--
 .../org/apache/juneau/parser/ParserSession.java | 99 +++++++++++++++++---
 .../plaintext/PlainTextParserBuilder.java       |  6 ++
 .../plaintext/PlainTextSerializerBuilder.java   |  6 ++
 .../juneau/remoteable/RemoteableMeta.java       |  2 +-
 .../juneau/serializer/SerializerBuilder.java    | 20 ++++
 .../juneau/serializer/SerializerContext.java    | 20 +++-
 .../serializer/SerializerGroupBuilder.java      | 15 ++-
 .../juneau/serializer/SerializerListener.java   | 46 +++++++++
 .../juneau/serializer/SerializerSession.java    | 27 +++++-
 .../juneau/soap/SoapXmlSerializerBuilder.java   |  7 ++
 .../java/org/apache/juneau/uon/UonParser.java   |  4 +-
 .../org/apache/juneau/uon/UonParserBuilder.java |  6 ++
 .../org/apache/juneau/uon/UonSerializer.java    |  2 +-
 .../apache/juneau/uon/UonSerializerBuilder.java |  6 ++
 .../juneau/urlencoding/UrlEncodingParser.java   |  4 +-
 .../urlencoding/UrlEncodingParserBuilder.java   |  7 ++
 .../urlencoding/UrlEncodingSerializer.java      |  2 +-
 .../UrlEncodingSerializerBuilder.java           |  7 ++
 .../java/org/apache/juneau/xml/XmlParser.java   |  4 +-
 .../org/apache/juneau/xml/XmlParserBuilder.java |  6 ++
 .../juneau/xml/XmlSchemaSerializerBuilder.java  |  7 ++
 .../org/apache/juneau/xml/XmlSerializer.java    |  6 +-
 .../apache/juneau/xml/XmlSerializerBuilder.java |  6 ++
 juneau-core/src/main/javadoc/overview.html      | 15 +++
 .../juneau/rest/client/RestClientBuilder.java   | 15 +++
 .../java/org/apache/juneau/rest/RestConfig.java | 32 +++++++
 .../org/apache/juneau/rest/RestContext.java     |  4 +-
 .../juneau/rest/annotation/RestResource.java    | 10 ++
 65 files changed, 615 insertions(+), 169 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
index 60e6b0b..ed9fc34 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
@@ -252,7 +252,7 @@ public class RdfParser extends ReaderParser {
 					pMeta.set(m, key, value);
 				}
 			} else if (! (p.equals(session.getRootProperty()) || p.equals(session.getTypeProperty()))) {
-				onUnknownProperty(session, key, m, -1, -1);
+				session.onUnknownProperty(key, m, -1, -1);
 			}
 			session.setCurrentProperty(null);
 		}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
index 03dbc48..f5ddfdc 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
@@ -349,6 +349,12 @@ public class RdfParserBuilder extends ParserBuilder {
 		return this;
 	}
 
+	@Override /* ParserBuilder */
+	public RdfParserBuilder listener(Class<? extends ParserListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public RdfParserBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
index 05dc92e..7ac3cde 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
@@ -368,7 +368,7 @@ public class RdfSerializer extends WriterSerializer {
 			Object value = bpv.getValue();
 			Throwable t = bpv.getThrown();
 			if (t != null)
-				session.addBeanGetterWarning(pMeta, t);
+				session.onBeanGetterException(pMeta, t);
 
 			if (session.canIgnoreValue(cMeta, key, value))
 				continue;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
index 91957a3..6bc1a50 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
@@ -524,6 +524,12 @@ public class RdfSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 	
+	@Override /* SerializerBuilder */
+	public RdfSerializerBuilder listener(Class<? extends SerializerListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public RdfSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core-test/src/test/java/org/apache/juneau/html/CommonParserTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/html/CommonParserTest.java b/juneau-core-test/src/test/java/org/apache/juneau/html/CommonParserTest.java
index 90f5c5c..8e4a059 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/html/CommonParserTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/html/CommonParserTest.java
@@ -142,21 +142,20 @@ public class CommonParserTest {
 	//====================================================================================================
 	@Test
 	public void testParserListeners() throws Exception {
-		final List<String> events = new LinkedList<String>();
-		HtmlParser p = new HtmlParserBuilder().ignoreUnknownBeanProperties(true).build();
-		p.addListener(
-			new ParserListener() {
-				@Override /* ParserListener */
-				public <T> void onUnknownProperty(String propertyName, Class<T> beanClass, T bean, int line, int col) {
-					events.add(propertyName + "," + line + "," + col);
-				}
-			}
-		);
+		HtmlParser p = new HtmlParserBuilder().ignoreUnknownBeanProperties(true).listener(MyParserListener.class).build();
 
 		String in = "<table _type='object'><tr><th><string>key</string></th><th><string>value</string></th></tr><tr><td><string>a</string></td><td><number>1</number></td></tr><tr><td><string>unknown</string></td><td><string>/foo</string></td></tr><tr><td><string>b</string></td><td><number>2</number></td></tr></table>";
 		p.parse(in, B.class);
-		assertEquals(1, events.size());
-		assertEquals("unknown,-1,-1", events.get(0));
+		assertEquals(1, MyParserListener.events.size());
+		assertEquals("unknown,-1,-1", MyParserListener.events.get(0));
 	}
+	
+	public static class MyParserListener extends ParserListener {
+		final static List<String> events = new LinkedList<String>();
 
+		@Override /* ParserListener */
+		public <T> void onUnknownBeanProperty(ParserSession session, String propertyName, Class<T> beanClass, T bean, int line, int col) {
+			events.add(propertyName + "," + line + "," + col);
+		}
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core-test/src/test/java/org/apache/juneau/jena/CommonParserTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/jena/CommonParserTest.java b/juneau-core-test/src/test/java/org/apache/juneau/jena/CommonParserTest.java
index dc59199..d7f2c0a 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/jena/CommonParserTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/jena/CommonParserTest.java
@@ -186,20 +186,20 @@ public class CommonParserTest {
 	//====================================================================================================
 	@Test
 	public void testParserListeners() throws Exception {
-		final List<String> events = new LinkedList<String>();
-		RdfParser p = new RdfParserBuilder().xml().ignoreUnknownBeanProperties(true).build();
-		p.addListener(
-			new ParserListener() {
-				@Override /* ParserListener */
-				public <T> void onUnknownProperty(String propertyName, Class<T> beanClass, T bean, int line, int col) {
-					events.add(propertyName + "," + line + "," + col);
-				}
-			}
-		);
+		RdfParser p = new RdfParserBuilder().xml().ignoreUnknownBeanProperties(true).listener(MyParserListener.class).build();
 
 		String in = wrap("<rdf:Description><jp:a rdf:datatype='http://www.w3.org/2001/XMLSchema#int'>1</jp:a><jp:unknownProperty>foo</jp:unknownProperty><jp:b rdf:datatype='http://www.w3.org/2001/XMLSchema#int'>2</jp:b></rdf:Description>");
 		p.parse(in, B.class);
-		assertEquals(1, events.size());
-		assertEquals("unknownProperty,-1,-1", events.get(0));
+		assertEquals(1, MyParserListener.events.size());
+		assertEquals("unknownProperty,-1,-1", MyParserListener.events.get(0));
+	}
+	
+	public static class MyParserListener extends ParserListener {
+		final static List<String> events = new LinkedList<String>();
+
+		@Override /* ParserListener */
+		public <T> void onUnknownBeanProperty(ParserSession session, String propertyName, Class<T> beanClass, T bean, int line, int col) {
+			events.add(propertyName + "," + line + "," + col);
+		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core-test/src/test/java/org/apache/juneau/json/CommonParserTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/json/CommonParserTest.java b/juneau-core-test/src/test/java/org/apache/juneau/json/CommonParserTest.java
index c3e4688..c9734a9 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/json/CommonParserTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/json/CommonParserTest.java
@@ -161,20 +161,20 @@ public class CommonParserTest {
 	//====================================================================================================
 	@Test
 	public void testParserListeners() throws Exception {
-		final List<String> events = new LinkedList<String>();
-		JsonParser p = new JsonParserBuilder().ignoreUnknownBeanProperties(true).build();
-		p.addListener(
-			new ParserListener() {
-				@Override /* ParserListener */
-				public <T> void onUnknownProperty(String propertyName, Class<T> beanClass, T bean, int line, int col) {
-					events.add(propertyName + "," + line + "," + col);
-				}
-			}
-		);
+		JsonParser p = new JsonParserBuilder().ignoreUnknownBeanProperties(true).listener(MyParserListener.class).build();
 
 		String json = "{a:1,unknownProperty:\"/foo\",b:2}";
 		p.parse(json, B.class);
-		assertEquals(1, events.size());
-		assertEquals("unknownProperty,1,5", events.get(0));
+		assertEquals(1, MyParserListener.events.size());
+		assertEquals("unknownProperty,1,5", MyParserListener.events.get(0));
+	}
+	
+	public static class MyParserListener extends ParserListener {
+		final static List<String> events = new LinkedList<String>();
+
+		@Override /* ParserListener */
+		public <T> void onUnknownBeanProperty(ParserSession session, String propertyName, Class<T> beanClass, T bean, int line, int col) {
+			events.add(propertyName + "," + line + "," + col);
+		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/CommonParser_UonTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/CommonParser_UonTest.java b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/CommonParser_UonTest.java
index 62a5d9d..ddb79f3 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/CommonParser_UonTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/CommonParser_UonTest.java
@@ -150,20 +150,20 @@ public class CommonParser_UonTest {
 	//====================================================================================================
 	@Test
 	public void testParserListeners() throws Exception {
-		final List<String> events = new LinkedList<String>();
-		UonParser p = new UonParserBuilder().ignoreUnknownBeanProperties(true).build();
-		p.addListener(
-			new ParserListener() {
-				@Override /* ParserListener */
-				public <T> void onUnknownProperty(String propertyName, Class<T> beanClass, T bean, int line, int col) {
-					events.add(propertyName + "," + line + "," + col);
-				}
-			}
-		);
+		UonParser p = new UonParserBuilder().ignoreUnknownBeanProperties(true).listener(MyParserListener.class).build();
 
 		String in = "(a=1,unknownProperty=foo,b=2)";
 		p.parse(in, B.class);
-		assertEquals(1, events.size());
-		assertEquals("unknownProperty,1,5", events.get(0));
+		assertEquals(1, MyParserListener.events.size());
+		assertEquals("unknownProperty,1,5", MyParserListener.events.get(0));
+	}
+	
+	public static class MyParserListener extends ParserListener {
+		final static List<String> events = new LinkedList<String>();
+
+		@Override /* ParserListener */
+		public <T> void onUnknownBeanProperty(ParserSession session, String propertyName, Class<T> beanClass, T bean, int line, int col) {
+			events.add(propertyName + "," + line + "," + col);
+		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/CommonParser_UrlEncodingTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/CommonParser_UrlEncodingTest.java b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/CommonParser_UrlEncodingTest.java
index d480a1b..a8f4e1a 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/CommonParser_UrlEncodingTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/CommonParser_UrlEncodingTest.java
@@ -152,21 +152,21 @@ public class CommonParser_UrlEncodingTest {
 	//====================================================================================================
 	@Test
 	public void testParserListeners() throws Exception {
-		final List<String> events = new LinkedList<String>();
-		UonParser p = new UrlEncodingParserBuilder().ignoreUnknownBeanProperties(true).build();
-		p.addListener(
-			new ParserListener() {
-				@Override /* ParserListener */
-				public <T> void onUnknownProperty(String propertyName, Class<T> beanClass, T bean, int line, int col) {
-					events.add(propertyName + "," + line + "," + col);
-				}
-			}
-		);
+		UonParser p = new UrlEncodingParserBuilder().ignoreUnknownBeanProperties(true).listener(MyParserListener.class).build();
 
 		String in = "a=1&unknownProperty=foo&b=2";
 		p.parse(in, B.class);
-		assertEquals(1, events.size());
-		assertEquals("unknownProperty,1,4", events.get(0));
+		assertEquals(1, MyParserListener.events.size());
+		assertEquals("unknownProperty,1,4", MyParserListener.events.get(0));
+	}
+
+	public static class MyParserListener extends ParserListener {
+		final static List<String> events = new LinkedList<String>();
+
+		@Override /* ParserListener */
+		public <T> void onUnknownBeanProperty(ParserSession session, String propertyName, Class<T> beanClass, T bean, int line, int col) {
+			events.add(propertyName + "," + line + "," + col);
+		}
 	}
 
 	@Test

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core-test/src/test/java/org/apache/juneau/xml/CommonParserTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/xml/CommonParserTest.java b/juneau-core-test/src/test/java/org/apache/juneau/xml/CommonParserTest.java
index 6c06dc3..73e1e4e1 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/xml/CommonParserTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/xml/CommonParserTest.java
@@ -158,21 +158,21 @@ public class CommonParserTest {
 	//====================================================================================================
 	@Test
 	public void testParserListeners() throws Exception {
-		final List<String> events = new LinkedList<String>();
-		XmlParser p = new XmlParserBuilder().ignoreUnknownBeanProperties(true).build();
-		p.addListener(
-			new ParserListener() {
-				@Override /* ParserListener */
-				public <T> void onUnknownProperty(String propertyName, Class<T> beanClass, T bean, int line, int col) {
-					events.add(propertyName + "," + line + "," + col);
-				}
-			}
-		);
+		XmlParser p = new XmlParserBuilder().ignoreUnknownBeanProperties(true).listener(MyParserListener.class).build();
 
 		String in = "<object><a _type='number'>1</a><unknownProperty _type='string'>foo</unknownProperty><b _type='number'>2</b></object>";
 		p.parse(in, B.class);
-		assertEquals(1, events.size());
+		assertEquals(1, MyParserListener.events.size());
 		// XML parser may or may not support line numbers.
-		assertTrue(events.get(0).startsWith("unknownProperty,"));
+		assertTrue(MyParserListener.events.get(0).startsWith("unknownProperty,"));
+	}
+	
+	public static class MyParserListener extends ParserListener {
+		final static List<String> events = new LinkedList<String>();
+
+		@Override /* ParserListener */
+		public <T> void onUnknownBeanProperty(ParserSession session, String propertyName, Class<T> beanClass, T bean, int line, int col) {
+			events.add(propertyName + "," + line + "," + col);
+		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/Session.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/Session.java b/juneau-core/src/main/java/org/apache/juneau/Session.java
index a75d197..d9bbfc8 100644
--- a/juneau-core/src/main/java/org/apache/juneau/Session.java
+++ b/juneau-core/src/main/java/org/apache/juneau/Session.java
@@ -59,7 +59,7 @@ public abstract class Session {
 	 * 	<li>Property defined on the context object.
 	 * 	<li>System.property.
 	 * </ul>
-	 * 
+	 *
 	 * @param key The property key.
 	 * @return The property value, or <jk>null</jk> if it doesn't exist.
 	 */
@@ -69,7 +69,7 @@ public abstract class Session {
 
 	/**
 	 * Same as {@link #getProperty(String)} but with a default value.
-	 * 
+	 *
 	 * @param key The property key.
 	 * @param def The default value if the property doesn't exist or is <jk>null</jk>.
 	 * @return The property value.
@@ -85,7 +85,7 @@ public abstract class Session {
 
 	/**
 	 * Same as {@link #getProperty(String)} but transforms the value to the specified type.
-	 * 
+	 *
 	 * @param type The class type of the value.
 	 * @param key The property key.
 	 * @return The property value.
@@ -96,7 +96,7 @@ public abstract class Session {
 
 	/**
 	 * Same as {@link #getProperty(Class,String)} but with a default value.
-	 * 
+	 *
 	 * @param type The class type of the value.
 	 * @param key The property key.
 	 * @param def The default value if the property doesn't exist or is <jk>null</jk>.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
index addbbb7..a33f9d6 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
@@ -77,6 +77,12 @@ public class CsvParserBuilder extends ParserBuilder {
 		return this;
 	}
 
+	@Override /* ParserBuilder */
+	public CsvParserBuilder listener(Class<? extends ParserListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public CsvParserBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
index eb002b3..e752a82 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
@@ -162,6 +162,12 @@ public class CsvSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
+	@Override /* SerializerBuilder */
+	public CsvSerializerBuilder listener(Class<? extends SerializerListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public CsvSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
index 2180fd1..be4546b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
@@ -13,6 +13,7 @@
 package org.apache.juneau.encoders;
 
 import static org.apache.juneau.internal.CollectionUtils.*;
+
 import java.util.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
index 3d80c7b..5376b0a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
@@ -461,7 +461,7 @@ public class HtmlParser extends XmlParser {
 				nextTag(r, TD);
 				BeanPropertyMeta pMeta = m.getPropertyMeta(key);
 				if (pMeta == null) {
-					onUnknownProperty(session, key, m, -1, -1);
+					session.onUnknownProperty(key, m, -1, -1);
 					parseAnything(session, object(), r, null, false, null);
 				} else {
 					ClassMeta<?> cm = pMeta.getClassMeta();

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
index 6c9f27c..4c2c283 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
@@ -19,6 +19,7 @@ import javax.xml.stream.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.parser.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -105,6 +106,12 @@ public class HtmlParserBuilder extends XmlParserBuilder {
 		return this;
 	}
 
+	@Override /* ParserBuilder */
+	public HtmlParserBuilder listener(Class<? extends ParserListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public HtmlParserBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
index 736e8c8..0bb39b8 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
@@ -381,7 +381,7 @@ public class HtmlSerializer extends XmlSerializer {
 			} catch (StackOverflowError t) {
 				throw t;
 			} catch (Throwable t) {
-				session.addWarning("Could not call getValue() on property ''{0}'', {1}", e.getKey(), t.getLocalizedMessage());
+				session.onError(t, "Could not call getValue() on property ''{0}'', {1}", e.getKey(), t.getLocalizedMessage());
 			}
 
 			out.sTag(i+1, "tr").nl();
@@ -429,7 +429,7 @@ public class HtmlSerializer extends XmlSerializer {
 			Object value = p.getValue();
 			Throwable t = p.getThrown();
 			if (t != null)
-				session.addBeanGetterWarning(pMeta, t);
+				session.onBeanGetterException(pMeta, t);
 
 			if (session.canIgnoreValue(cMeta, key, value))
 				continue;
@@ -456,7 +456,7 @@ public class HtmlSerializer extends XmlSerializer {
 				throw e;
 			} catch (Throwable e) {
 				e.printStackTrace();
-				session.addBeanGetterWarning(pMeta, e);
+				session.onBeanGetterException(pMeta, e);
 			}
 			out.eTag("td").nl();
 			out.eTag(i+1, "tr").nl();

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
index b9a7fad..c2f4112 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
@@ -18,6 +18,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.serializer.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -334,6 +335,12 @@ public class HtmlSerializerBuilder extends XmlSerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
+	public HtmlSerializerBuilder listener(Class<? extends SerializerListener> value) {
+		super.listener(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
 	public HtmlSerializerBuilder sortMaps(boolean value) {
 		super.sortMaps(value);
 		return this;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileBuilder.java b/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileBuilder.java
index 5d44f10..67a1693 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileBuilder.java
@@ -17,6 +17,7 @@ import static org.apache.juneau.ini.ConfigFileFormat.*;
 import java.io.*;
 import java.nio.charset.*;
 import java.util.*;
+
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
index 3b31bfc..f3163d3 100644
--- a/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
@@ -739,4 +739,24 @@ public final class ClassUtils {
 			returnType = BeanContext.DEFAULT.getClassMeta(m.getGenericReturnType()).toString();
 		}
 	}
+
+	/**
+	 * Creates an instance of the specified class without throwing exceptions.
+	 *
+	 * @param c The class to instantiate.
+	 * @param args The arguments to pass to the constructor.
+	 * @return The new class instance, or <jk>null</jk> if the class was <jk>null</jk>.
+	 * @throws RuntimeException if constructor could not be found or called.
+	 */
+	public static <T> T newInstance(Class<T> c, Object...args) {
+		if (c == null)
+			return null;
+		try {
+			if (args.length == 0)
+				return c.newInstance();
+			return c.getConstructor(getClasses(args)).newInstance(args);
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/internal/StringUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/StringUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/StringUtils.java
index d17bc58..c4bf1db 100644
--- a/juneau-core/src/main/java/org/apache/juneau/internal/StringUtils.java
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/StringUtils.java
@@ -26,7 +26,6 @@ import java.util.regex.*;
 import javax.xml.bind.*;
 
 import org.apache.juneau.parser.*;
-import org.apache.juneau.parser.ParseException;
 
 /**
  * Reusable string utility methods.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
index 210460b..aa5e448 100644
--- a/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
@@ -78,6 +78,12 @@ public class JsoParserBuilder extends ParserBuilder {
 		return this;
 	}
 
+	@Override /* ParserBuilder */
+	public JsoParserBuilder listener(Class<? extends ParserListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public JsoParserBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
index 3508985..1da92e6 100644
--- a/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
@@ -162,6 +162,12 @@ public class JsoSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
+	@Override /* SerializerBuilder */
+	public JsoSerializerBuilder listener(Class<? extends SerializerListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public JsoSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
index 490eed1..8fb7fd2 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
@@ -498,7 +498,7 @@ public class JsonParser extends ReaderParser {
 						BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
 						session.setCurrentProperty(pMeta);
 						if (pMeta == null) {
-							onUnknownProperty(session, currAttr, m, currAttrLine, currAttrCol);
+							session.onUnknownProperty(currAttr, m, currAttrLine, currAttrCol);
 							parseAnything(session, object(), r.unread(), m.getBean(false), null); // Read content anyway to ignore it
 						} else {
 							ClassMeta<?> cm = pMeta.getClassMeta();

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
index 1d6a3ad..40cfd30 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
@@ -78,6 +78,12 @@ public class JsonParserBuilder extends ParserBuilder {
 		return this;
 	}
 
+	@Override /* ParserBuilder */
+	public JsonParserBuilder listener(Class<? extends ParserListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public JsonParserBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
index 112cbee..d58aca2 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
@@ -16,6 +16,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.serializer.*;
 
 /**
  * Builder class for building instances of JSON Schema serializers.
@@ -179,6 +180,12 @@ public class JsonSchemaSerializerBuilder extends JsonSerializerBuilder {
 		return this;
 	}
 
+	@Override /* SerializerBuilder */
+	public JsonSchemaSerializerBuilder listener(Class<? extends SerializerListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public JsonSchemaSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
index 1037e60..4ec9298 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
@@ -322,7 +322,7 @@ public class JsonSerializer extends WriterSerializer {
 			Object value = p.getValue();
 			Throwable t = p.getThrown();
 			if (t != null)
-				session.addBeanGetterWarning(pMeta, t);
+				session.onBeanGetterException(pMeta, t);
 
 			if (session.canIgnoreValue(cMeta, key, value))
 				continue;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
index 33be93f..98ed08c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
@@ -227,6 +227,12 @@ public class JsonSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
+	@Override /* SerializerBuilder */
+	public JsonSerializerBuilder listener(Class<? extends SerializerListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public JsonSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
index 51ec189..b02ee46 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
@@ -131,7 +131,7 @@ public class MsgPackParser extends InputStreamParser {
 							if (pName.equals(session.getBeanTypePropertyName(eType)))
 								parseAnything(session, session.string(), is, null, null);
 							else
-								onUnknownProperty(session, pName, m, 0, is.getPosition());
+								session.onUnknownProperty(pName, m, 0, is.getPosition());
 						} else {
 							ClassMeta<?> cm = bpm.getClassMeta();
 							Object value = parseAnything(session, cm, is, m.getBean(false), bpm);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
index 26df53b..38d2841 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
@@ -78,6 +78,12 @@ public class MsgPackParserBuilder extends ParserBuilder {
 		return this;
 	}
 
+	@Override /* ParserBuilder */
+	public MsgPackParserBuilder listener(Class<? extends ParserListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public MsgPackParserBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
index c47b630..0f4949c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
@@ -172,7 +172,7 @@ public class MsgPackSerializer extends OutputStreamSerializer {
 			Object value = p.getValue();
 			Throwable t = p.getThrown();
 			if (t != null)
-				session.addBeanGetterWarning(pMeta, t);
+				session.onBeanGetterException(pMeta, t);
 			else {
 				serializeAnything(session, out, key, null, null, null);
 				serializeAnything(session, out, value, cMeta, key, pMeta);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
index 36ebe9f..fc4935f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
@@ -162,6 +162,12 @@ public class MsgPackSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
+	@Override /* SerializerBuilder */
+	public MsgPackSerializerBuilder listener(Class<? extends SerializerListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public MsgPackSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java b/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
index a1f00a0..38c6d16 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
@@ -134,7 +134,6 @@ import org.apache.juneau.utils.*;
 public abstract class Parser extends CoreObject {
 
 	/** General parser properties currently set on this parser. */
-	private final List<ParserListener> listeners = new LinkedList<ParserListener>();
 	private final MediaType[] mediaTypes;
 	private final ParserContext ctx;
 
@@ -506,26 +505,6 @@ public abstract class Parser extends CoreObject {
 	//--------------------------------------------------------------------------------
 
 	/**
-	 * Adds a {@link ParserListener} to this parser to listen for parse events.
-	 *
-	 * @param listener The listener to associate with this parser.
-	 * @return This object (for method chaining).
-	 */
-	public Parser addListener(ParserListener listener) {
-		this.listeners.add(listener);
-		return this;
-	}
-
-	/**
-	 * Returns the current parser listeners associated with this parser.
-	 *
-	 * @return The current list of parser listeners.
-	 */
-	public List<ParserListener> getListeners() {
-		return listeners;
-	}
-
-	/**
 	 * Converts the specified string to the specified type.
 	 *
 	 * @param session The session object.
@@ -602,29 +581,6 @@ public abstract class Parser extends CoreObject {
 	}
 
 	/**
-	 * Method that gets called when an unknown bean property name is encountered.
-	 *
-	 * @param session The parser session.
-	 * @param propertyName The unknown bean property name.
-	 * @param beanMap The bean that doesn't have the expected property.
-	 * @param line The line number where the property was found.  <code>-1</code> if line numbers are not available.
-	 * @param col The column number where the property was found.  <code>-1</code> if column numbers are not available.
-	 * @throws ParseException Automatically thrown if {@link BeanContext#BEAN_ignoreUnknownBeanProperties} setting
-	 * 	on this parser is <jk>false</jk>
-	 * @param <T> The class type of the bean map that doesn't have the expected property.
-	 */
-	protected <T> void onUnknownProperty(ParserSession session, String propertyName, BeanMap<T> beanMap, int line, int col) throws ParseException {
-		if (propertyName.equals(session.getBeanTypePropertyName(beanMap.getClassMeta())))
-			return;
-		if (! session.isIgnoreUnknownBeanProperties())
-			throw new ParseException(session, "Unknown property ''{0}'' encountered while trying to parse into class ''{1}''", propertyName, beanMap.getClassMeta());
-		if (listeners.size() > 0)
-			for (ParserListener listener : listeners)
-				listener.onUnknownProperty(propertyName, beanMap.getClassMeta().getInnerClass(), beanMap.getBean(), line, col);
-	}
-
-
-	/**
 	 * Returns the media types handled based on the value of the {@link Consumes} annotation on the parser class.
 	 * <p>
 	 * This method can be overridden by subclasses to determine the media types programatically.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
index bdf3cf3..dbc9d86 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
@@ -192,6 +192,26 @@ public class ParserBuilder extends CoreObjectBuilder {
 		return property(PARSER_fileCharset, value);
 	}
 
+	/**
+	 * <b>Configuration property:</b>  Parser listener.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Parser.listener"</js>
+	 * 	<li><b>Data type:</b> <code>Class&lt;? extends ParserListener&gt;</code>
+	 * 	<li><b>Default:</b> <jk>null</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Class used to listen for errors and warnings that occur during parsing.
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see ParserContext#PARSER_listener
+	 */
+	public ParserBuilder listener(Class<? extends ParserListener> value) {
+		return property(PARSER_listener, value);
+	}
+
 	@Override /* CoreObjectBuilder */
 	public ParserBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/parser/ParserContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserContext.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserContext.java
index e0ee73c..bff9dec 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserContext.java
@@ -110,21 +110,37 @@ public class ParserContext extends BeanContext {
 	 */
 	public static final String PARSER_fileCharset = "Parser.fileCharset";
 
+	/**
+	 * <b>Configuration property:</b>  Parser listener.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Parser.listener"</js>
+	 * 	<li><b>Data type:</b> <code>Class&lt;? extends ParserListener&gt;</code>
+	 * 	<li><b>Default:</b> <jk>null</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Class used to listen for errors and warnings that occur during parsing.
+	 */
+	public static final String PARSER_listener = "PARSER.listener";
 
 	final boolean trimStrings, strict;
 	final String inputStreamCharset, fileCharset;
+	final Class<? extends ParserListener> listener;
 
 	/**
 	 * Constructor.
 	 *
 	 * @param ps The property store that created this context.
 	 */
+	@SuppressWarnings("unchecked")
 	public ParserContext(PropertyStore ps) {
 		super(ps);
 		this.trimStrings = ps.getProperty(PARSER_trimStrings, boolean.class, false);
 		this.strict = ps.getProperty(PARSER_strict, boolean.class, false);
 		this.inputStreamCharset = ps.getProperty(PARSER_inputStreamCharset, String.class, "UTF-8");
 		this.fileCharset = ps.getProperty(PARSER_fileCharset, String.class, "default");
+		this.listener = ps.getProperty(PARSER_listener, Class.class, null);
 	}
 
 	@Override /* Context */
@@ -135,6 +151,7 @@ public class ParserContext extends BeanContext {
 				.append("strict", strict)
 				.append("inputStreamCharset", inputStreamCharset)
 				.append("fileCharset", fileCharset)
+				.append("listener", listener)
 			);
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
index 06383a9..f9dc3f3 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
@@ -252,6 +252,17 @@ public class ParserGroupBuilder {
 	}
 
 	/**
+	 * Sets the {@link ParserContext#PARSER_listener} property on all parsers in this group.
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see ParserContext#PARSER_listener
+	 */
+	public ParserGroupBuilder listener(Class<? extends ParserListener> value) {
+		return property(PARSER_listener, value);
+	}
+
+	/**
 	 * Sets the {@link BeanContext#BEAN_beansRequireDefaultConstructor} property on all parsers in this group.
 	 *
 	 * @param value The new value for this property.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/parser/ParserListener.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserListener.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserListener.java
index 9c01704..dd1989d 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserListener.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserListener.java
@@ -12,14 +12,12 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.parser;
 
+import java.text.*;
+
 import org.apache.juneau.*;
 
 /**
  * Class for listening for certain parse events during a document parse.
- * <p>
- * Listeners can be registered with parsers through the {@link Parser#addListener(ParserListener)} method.
- * <p>
- * It should be noted that listeners are not automatically copied over to new parsers when a parser is cloned using the {@link Parser#builder()} method.
  */
 public class ParserListener {
 
@@ -30,13 +28,29 @@ public class ParserListener {
 	 * Otherwise, the parser will throw a {@link ParseException}.
 	 *
 	 * @param <T> The class type of the bean.
+	 * @param session The parser session.
+	 * 	Note that if {@link BeanContext#BEAN_debug} is enabled on the parser, you can get the input as a string through
+	 * 	{@link ParserSession#getInputAsString()}.
 	 * @param propertyName The property name encountered in the document.
 	 * @param beanClass The bean class.
 	 * @param bean The bean.
 	 * @param line The line number where the unknown property was found (-1 if parser doesn't support line/column indicators).
 	 * @param col The column number where the unknown property was found (-1 if parser doesn't support line/column indicators).
 	 */
-	public <T> void onUnknownProperty(String propertyName, Class<T> beanClass, T bean, int line, int col) {
-		// Do something with information
+	public <T> void onUnknownBeanProperty(ParserSession session, String propertyName, Class<T> beanClass, T bean, int line, int col) {
+		onError(session, null, MessageFormat.format("Unknown property ''{0}'' encountered while trying to parse into class ''{1}'' at line {2} column {3}", propertyName, beanClass, line, col));
+	}
+
+	/**
+	 * Called when an error occurs during parsing but is ignored.
+	 *
+	 * @param session The parsers session.
+	 * 	Note that if {@link BeanContext#BEAN_debug} is enabled on the parser, you can get the input as a string through
+	 * 	{@link ParserSession#getInputAsString()}.
+	 * @param t The throwable that was thrown by the getter method.
+	 * @param msg The error message.
+	 */
+	public void onError(ParserSession session, Throwable t, String msg) {
+		// Do something with this information.
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
index 5704dce..0b28ce6 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
@@ -36,10 +36,12 @@ public class ParserSession extends BeanSession {
 	private final Method javaMethod;
 	private final Object outer;
 	private final Object input;
+	private String inputString;
 	private InputStream inputStream;
 	private Reader reader, noCloseReader;
 	private BeanPropertyMeta currentProperty;
 	private ClassMeta<?> currentClass;
+	private final ParserListener listener;
 
 	/**
 	 * Create a new session using properties specified in the context.
@@ -73,22 +75,31 @@ public class ParserSession extends BeanSession {
 	 * If <jk>null</jk>, then the timezone defined on the context is used.
 	 * @param mediaType The session media type (e.g. <js>"application/json"</js>).
 	 */
+	@SuppressWarnings("unchecked")
 	public ParserSession(ParserContext ctx, ObjectMap op, Object input, Method javaMethod, Object outer, Locale locale, TimeZone timeZone, MediaType mediaType) {
 		super(ctx, op, locale, timeZone, mediaType);
+		Class<? extends ParserListener> listenerClass;
 		if (op == null || op.isEmpty()) {
 			trimStrings = ctx.trimStrings;
 			strict = ctx.strict;
 			inputStreamCharset = ctx.inputStreamCharset;
 			fileCharset = ctx.fileCharset;
+			listenerClass = ctx.listener;
 		} else {
 			trimStrings = op.getBoolean(PARSER_trimStrings, ctx.trimStrings);
 			strict = op.getBoolean(PARSER_strict, ctx.strict);
 			inputStreamCharset = op.getString(PARSER_inputStreamCharset, ctx.inputStreamCharset);
 			fileCharset = op.getString(PARSER_fileCharset, ctx.fileCharset);
+			listenerClass = op.get(Class.class, PARSER_listener, ctx.listener);
 		}
 		this.input = input;
 		this.javaMethod = javaMethod;
 		this.outer = outer;
+		try {
+			this.listener = listenerClass == null ? null : listenerClass.newInstance();
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
 	}
 
 	/**
@@ -99,21 +110,38 @@ public class ParserSession extends BeanSession {
 	 * @throws ParseException If object could not be converted to an input stream.
 	 */
 	public InputStream getInputStream() throws ParseException {
-		if (input == null)
-			return null;
-		if (input instanceof InputStream)
-			return (InputStream)input;
-		if (input instanceof byte[])
-			return new ByteArrayInputStream((byte[])input);
-		if (input instanceof String)
-			return new ByteArrayInputStream(StringUtils.fromHex((String)input));
-		if (input instanceof File)
-			try {
+		try {
+			if (input == null)
+				return null;
+			if (input instanceof InputStream) {
+				if (isDebug()) {
+					byte[] b = IOUtils.readBytes((InputStream)input, 1024);
+					inputString = StringUtils.toHex(b);
+					return new ByteArrayInputStream(b);
+				}
+				return (InputStream)input;
+			}
+			if (input instanceof byte[]) {
+				if (isDebug())
+					inputString = StringUtils.toHex((byte[])input);
+				return new ByteArrayInputStream((byte[])input);
+			}
+			if (input instanceof String) {
+				inputString = (String)input;
+				return new ByteArrayInputStream(StringUtils.fromHex((String)input));
+			}
+			if (input instanceof File) {
+				if (isDebug()) {
+					byte[] b = IOUtils.readBytes((File)input);
+					inputString = StringUtils.toHex(b);
+					return new ByteArrayInputStream(b);
+				}
 				inputStream = new FileInputStream((File)input);
 				return inputStream;
-			} catch (FileNotFoundException e) {
-				throw new ParseException(e);
 			}
+		} catch (IOException e) {
+			throw new ParseException(e);
+		}
 		throw new ParseException("Cannot convert object of type {0} to an InputStream.", input.getClass().getName());
 	}
 
@@ -128,9 +156,15 @@ public class ParserSession extends BeanSession {
 	public Reader getReader() throws Exception {
 		if (input == null)
 			return null;
-		if (input instanceof Reader)
+		if (input instanceof Reader) {
+			if (isDebug()) {
+				inputString = IOUtils.read((Reader)input);
+				return new StringReader(inputString);
+			}
 			return (Reader)input;
+		}
 		if (input instanceof CharSequence) {
+			inputString = input.toString();
 			if (reader == null)
 				reader = new ParserReader((CharSequence)input);
 			return reader;
@@ -148,6 +182,10 @@ public class ParserSession extends BeanSession {
 				}
 				noCloseReader = new InputStreamReader(is, cd);
 			}
+			if (isDebug()) {
+				inputString = IOUtils.read(noCloseReader);
+				return new StringReader(inputString);
+			}
 			return noCloseReader;
 		}
 		if (input instanceof File) {
@@ -162,6 +200,10 @@ public class ParserSession extends BeanSession {
 				}
 				reader = new InputStreamReader(new FileInputStream((File)input), cd);
 			}
+			if (isDebug()) {
+				inputString = IOUtils.read(reader);
+				return new StringReader(inputString);
+			}
 			return reader;
 		}
 		throw new ParseException("Cannot convert object of type {0} to a Reader.", input.getClass().getName());
@@ -344,6 +386,37 @@ public class ParserSession extends BeanSession {
 	}
 
 	/**
+	 * Method that gets called when an unknown bean property name is encountered.
+	 *
+	 * @param propertyName The unknown bean property name.
+	 * @param beanMap The bean that doesn't have the expected property.
+	 * @param line The line number where the property was found.  <code>-1</code> if line numbers are not available.
+	 * @param col The column number where the property was found.  <code>-1</code> if column numbers are not available.
+	 * @throws ParseException Automatically thrown if {@link BeanContext#BEAN_ignoreUnknownBeanProperties} setting
+	 * 	on this parser is <jk>false</jk>
+	 * @param <T> The class type of the bean map that doesn't have the expected property.
+	 */
+	public <T> void onUnknownProperty(String propertyName, BeanMap<T> beanMap, int line, int col) throws ParseException {
+		if (propertyName.equals(getBeanTypePropertyName(beanMap.getClassMeta())))
+			return;
+		if (! isIgnoreUnknownBeanProperties())
+			throw new ParseException(this, "Unknown property ''{0}'' encountered while trying to parse into class ''{1}''", propertyName, beanMap.getClassMeta());
+		if (listener != null)
+			listener.onUnknownBeanProperty(this, propertyName, beanMap.getClassMeta().getInnerClass(), beanMap.getBean(), line, col);
+	}
+
+	/**
+	 * Returns the input to this parser as a plain string.
+	 * <p>
+	 * This method only returns a value if {@link BeanContext#BEAN_debug} is enabled.
+	 *
+	 * @return The input as a string, or <jk>null</jk> if debug mode not enabled.
+	 */
+	public String getInputAsString() {
+		return inputString;
+	}
+
+	/**
 	 * Perform cleanup on this context object if necessary.
 	 */
 	@Override

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
index bb60f4c..9f9177d 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
@@ -78,6 +78,12 @@ public class PlainTextParserBuilder extends ParserBuilder {
 		return this;
 	}
 
+	@Override /* ParserBuilder */
+	public PlainTextParserBuilder listener(Class<? extends ParserListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public PlainTextParserBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
index 596fed2..883053a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
@@ -162,6 +162,12 @@ public class PlainTextSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
+	@Override /* SerializerBuilder */
+	public PlainTextSerializerBuilder listener(Class<? extends SerializerListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public PlainTextSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMeta.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMeta.java
index 98ea600..0fb31b2 100644
--- a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMeta.java
@@ -12,8 +12,8 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.remoteable;
 
-import static org.apache.juneau.internal.StringUtils.*;
 import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
 
 import java.lang.reflect.*;
 import java.util.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
index 79d6a29..3716d23 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
@@ -557,6 +557,26 @@ public class SerializerBuilder extends CoreObjectBuilder {
 		return property(SERIALIZER_abridged, value);
 	}
 
+	/**
+	 * <b>Configuration property:</b>  Serializer listener.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.listener"</js>
+	 * 	<li><b>Data type:</b> <code>Class&lt;? extends SerializerListener&gt;</code>
+	 * 	<li><b>Default:</b> <jk>null</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Class used to listen for errors and warnings that occur during serialization.
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_listener
+	 */
+	public SerializerBuilder listener(Class<? extends SerializerListener> value) {
+		return property(SERIALIZER_listener, value);
+	}
+
 	@Override /* CoreObjectBuilder */
 	public SerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
index 372e8e0..1381972 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
@@ -320,7 +320,7 @@ public class SerializerContext extends BeanContext {
 	 * <b>Configuration property:</b>  Abridged output.
 	 * <p>
 	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.parserKnowsRootType"</js>
+	 * 	<li><b>Name:</b> <js>"Serializer.abridged"</js>
 	 * 	<li><b>Data type:</b> <code>Boolean</code>
 	 * 	<li><b>Default:</b> <jk>false</jk>
 	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
@@ -335,6 +335,20 @@ public class SerializerContext extends BeanContext {
 	 */
 	public static final String SERIALIZER_abridged = "Serializer.abridged";
 
+	/**
+	 * <b>Configuration property:</b>  Serializer listener.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.listener"</js>
+	 * 	<li><b>Data type:</b> <code>Class&lt;? extends SerializerListener&gt;</code>
+	 * 	<li><b>Default:</b> <jk>null</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Class used to listen for errors and warnings that occur during serialization.
+	 */
+	public static final String SERIALIZER_listener = "Serializer.listener";
+
 
 	final int maxDepth, initialDepth;
 	final boolean
@@ -353,12 +367,14 @@ public class SerializerContext extends BeanContext {
 	final UriContext uriContext;
 	final UriResolution uriResolution;
 	final UriRelativity uriRelativity;
+	final Class<? extends SerializerListener> listener;
 
 	/**
 	 * Constructor.
 	 *
 	 * @param ps The property store that created this context.
 	 */
+	@SuppressWarnings("unchecked")
 	public SerializerContext(PropertyStore ps) {
 		super(ps);
 		maxDepth = ps.getProperty(SERIALIZER_maxDepth, int.class, 100);
@@ -378,6 +394,7 @@ public class SerializerContext extends BeanContext {
 		uriContext = ps.getProperty(SERIALIZER_uriContext, UriContext.class, UriContext.DEFAULT);
 		uriResolution = ps.getProperty(SERIALIZER_uriResolution, UriResolution.class, UriResolution.ROOT_RELATIVE);
 		uriRelativity = ps.getProperty(SERIALIZER_uriRelativity, UriRelativity.class, UriRelativity.RESOURCE);
+		listener = ps.getProperty(SERIALIZER_listener, Class.class, null);
 	}
 
 	@Override /* Context */
@@ -401,6 +418,7 @@ public class SerializerContext extends BeanContext {
 				.append("uriContext", uriContext)
 				.append("uriResolution", uriResolution)
 				.append("uriRelativity", uriRelativity)
+				.append("listener", listener)
 			);
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
index bbe7577..d34b07f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
@@ -13,8 +13,8 @@
 package org.apache.juneau.serializer;
 
 import static org.apache.juneau.BeanContext.*;
-import static org.apache.juneau.serializer.SerializerContext.*;
 import static org.apache.juneau.internal.CollectionUtils.*;
+import static org.apache.juneau.serializer.SerializerContext.*;
 
 import java.util.*;
 
@@ -408,11 +408,22 @@ public class SerializerGroupBuilder {
 	 * @return This object (for method chaining).
 	 * @see SerializerContext#SERIALIZER_abridged
 	 */
-	public SerializerGroupBuilder parserKnowsRootType(boolean value) {
+	public SerializerGroupBuilder abridged(boolean value) {
 		return property(SERIALIZER_abridged, value);
 	}
 
 	/**
+	 * Sets the {@link SerializerContext#SERIALIZER_listener} property on all serializers in this group.
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_listener
+	 */
+	public SerializerGroupBuilder listener(Class<? extends SerializerListener> value) {
+		return property(SERIALIZER_listener, value);
+	}
+
+	/**
 	 * Sets the {@link BeanContext#BEAN_beansRequireDefaultConstructor} property on all serializers in this group.
 	 *
 	 * @param value The new value for this property.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerListener.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerListener.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerListener.java
new file mode 100644
index 0000000..9125063
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerListener.java
@@ -0,0 +1,46 @@
+// ***************************************************************************************************************************
+// * 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.juneau.serializer;
+
+import java.text.*;
+
+import org.apache.juneau.*;
+
+/**
+ * Class for listening for serialize events during a serialization.
+ */
+public class SerializerListener {
+
+	/**
+	 * Called when an exception is thrown when trying to call a bean getter method.
+	 *
+	 * @param session The serializer session.
+	 * 	Note that if
+	 * @param t The throwable that was thrown by the getter method.
+	 * @param p The bean property we had an issue on.
+	 */
+	public void onBeanGetterException(SerializerSession session, Throwable t, BeanPropertyMeta p) {
+		onError(session, t, MessageFormat.format("Could not call getValue() on property ''{1}'' of class ''{2}'', exception = {3}", p.getName(), p.getBeanMeta().getClassMeta(), t.getLocalizedMessage()));
+	}
+
+	/**
+	 * Called when an error occurs during serialization but is ignored.
+	 *
+	 * @param session The serializer session.
+	 * @param t The throwable that was thrown by the getter method.
+	 * @param msg The error message.
+	 */
+	public void onError(SerializerSession session, Throwable t, String msg) {
+		// Do something with this information.
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
index 9a96a30..a52314a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
@@ -17,6 +17,7 @@ import static org.apache.juneau.serializer.SerializerContext.*;
 
 import java.io.*;
 import java.lang.reflect.*;
+import java.text.*;
 import java.util.*;
 
 import org.apache.juneau.*;
@@ -67,6 +68,7 @@ public class SerializerSession extends BeanSession {
 	private Writer writer, flushOnlyWriter;
 	private BeanPropertyMeta currentProperty;
 	private ClassMeta<?> currentClass;
+	private final SerializerListener listener;
 
 
 	/**
@@ -97,12 +99,14 @@ public class SerializerSession extends BeanSession {
 	 * @param uriContext The URI context.
 	 * 	Identifies the current request URI used for resolution of URIs to absolute or root-relative form.
 	 */
+	@SuppressWarnings("unchecked")
 	public SerializerSession(SerializerContext ctx, ObjectMap op, Object output, Method javaMethod, Locale locale, TimeZone timeZone, MediaType mediaType, UriContext uriContext) {
 		super(ctx, op, locale, timeZone, mediaType);
 		this.javaMethod = javaMethod;
 		this.output = output;
 		UriResolution uriResolution;
 		UriRelativity uriRelativity;
+		Class<? extends SerializerListener> listenerClass;
 		if (op == null || op.isEmpty()) {
 			maxDepth = ctx.maxDepth;
 			initialDepth = ctx.initialDepth;
@@ -120,6 +124,7 @@ public class SerializerSession extends BeanSession {
 			abridged = ctx.abridged;
 			uriResolution = ctx.uriResolution;
 			uriRelativity = ctx.uriRelativity;
+			listenerClass = ctx.listener;
 		} else {
 			maxDepth = op.getInt(SERIALIZER_maxDepth, ctx.maxDepth);
 			initialDepth = op.getInt(SERIALIZER_initialDepth, ctx.initialDepth);
@@ -137,10 +142,13 @@ public class SerializerSession extends BeanSession {
 			abridged = op.getBoolean(SERIALIZER_abridged, ctx.abridged);
 			uriResolution = op.get(UriResolution.class, SERIALIZER_uriResolution, UriResolution.ROOT_RELATIVE);
 			uriRelativity = op.get(UriRelativity.class, SERIALIZER_uriRelativity, UriRelativity.RESOURCE);
+			listenerClass = op.get(Class.class, SERIALIZER_listener, ctx.listener);
 		}
 
 		uriResolver = new UriResolver(uriResolution, uriRelativity, uriContext == null ? ctx.uriContext : uriContext);
 
+		listener = ClassUtils.newInstance(listenerClass);
+
 		this.indent = initialDepth;
 		if (detectRecursions || isDebug()) {
 			set = new IdentityHashMap<Object,Object>();
@@ -435,7 +443,7 @@ public class SerializerSession extends BeanSession {
 			Object o = stack.removeLast().o;
 			Object o2 = set.remove(o);
 			if (o2 == null)
-				addWarning("Couldn't remove object of type ''{0}'' on attribute ''{1}'' from object stack.", o.getClass().getName(), stack);
+				onError(null, "Couldn't remove object of type ''{0}'' on attribute ''{1}'' from object stack.", o.getClass().getName(), stack);
 		}
 		isBottom = false;
 	}
@@ -455,12 +463,27 @@ public class SerializerSession extends BeanSession {
 	 * @param p The bean map entry representing the bean property.
 	 * @param t The throwable that the bean getter threw.
 	 */
-	public void addBeanGetterWarning(BeanPropertyMeta p, Throwable t) {
+	public void onBeanGetterException(BeanPropertyMeta p, Throwable t) {
+		if (listener != null)
+			listener.onBeanGetterException(this, t, p);
 		String prefix = (isDebug() ? getStack(false) + ": " : "");
 		addWarning("{0}Could not call getValue() on property ''{1}'' of class ''{2}'', exception = {3}", prefix, p.getName(), p.getBeanMeta().getClassMeta(), t.getLocalizedMessage());
 	}
 
 	/**
+	 * Logs a warning message.
+	 *
+	 * @param t The throwable that was thrown (if there was one).
+	 * @param msg The warning message.
+	 * @param args Optional {@link MessageFormat}-style arguments.
+	 */
+	public final void onError(Throwable t, String msg, Object... args) {
+		if (listener != null)
+			listener.onError(this, t, MessageFormat.format(msg, args));
+		super.addWarning(msg, args);
+	}
+
+	/**
 	 * Trims the specified string if {@link SerializerSession#isTrimStrings()} returns <jk>true</jk>.
 	 *
 	 * @param o The input string to trim.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
index 015e662..ad67be4 100644
--- a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
@@ -18,6 +18,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.serializer.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -223,6 +224,12 @@ public class SoapXmlSerializerBuilder extends XmlSerializerBuilder {
 		return this;
 	}
 
+	@Override /* SerializerBuilder */
+	public SoapXmlSerializerBuilder listener(Class<? extends SerializerListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public SoapXmlSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
index 020a2f4..32ea7b4 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
@@ -458,7 +458,7 @@ public class UonParser extends ReaderParser {
 						if (! currAttr.equals(session.getBeanTypePropertyName(m.getClassMeta()))) {
 							BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
 							if (pMeta == null) {
-								onUnknownProperty(session, currAttr, m, currAttrLine, currAttrCol);
+								session.onUnknownProperty(currAttr, m, currAttrLine, currAttrCol);
 							} else {
 								Object value = session.convertToType("", pMeta.getClassMeta());
 								pMeta.set(m, currAttr, value);
@@ -471,7 +471,7 @@ public class UonParser extends ReaderParser {
 						if (! currAttr.equals(session.getBeanTypePropertyName(m.getClassMeta()))) {
 							BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
 							if (pMeta == null) {
-								onUnknownProperty(session, currAttr, m, currAttrLine, currAttrCol);
+								session.onUnknownProperty(currAttr, m, currAttrLine, currAttrCol);
 								parseAnything(session, object(), r.unread(), m.getBean(false), false, null); // Read content anyway to ignore it
 							} else {
 								session.setCurrentProperty(pMeta);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
index ef29a73..4d1f576 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
@@ -116,6 +116,12 @@ public class UonParserBuilder extends ParserBuilder {
 		return this;
 	}
 
+	@Override /* ParserBuilder */
+	public UonParserBuilder listener(Class<? extends ParserListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public UonParserBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java
index 8eed75b..96901d2 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java
@@ -327,7 +327,7 @@ public class UonSerializer extends WriterSerializer {
 			Object value = p.getValue();
 			Throwable t = p.getThrown();
 			if (t != null)
-				session.addBeanGetterWarning(pMeta, t);
+				session.onBeanGetterException(pMeta, t);
 
 			if (session.canIgnoreValue(cMeta, key, value))
 				continue;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
index 3d0ee3d..b64350e 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
@@ -204,6 +204,12 @@ public class UonSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder listener(Class<? extends SerializerListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public UonSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
index cb9f19c..800129f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
@@ -269,7 +269,7 @@ public class UrlEncodingParser extends UonParser {
 						if (! currAttr.equals(session.getBeanTypePropertyName(m.getClassMeta()))) {
 							BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
 							if (pMeta == null) {
-								onUnknownProperty(session, currAttr, m, currAttrLine, currAttrCol);
+								session.onUnknownProperty(currAttr, m, currAttrLine, currAttrCol);
 							} else {
 								session.setCurrentProperty(pMeta);
 								// In cases of "&foo=", create an empty instance of the value if createable.
@@ -287,7 +287,7 @@ public class UrlEncodingParser extends UonParser {
 						if (! currAttr.equals(session.getBeanTypePropertyName(m.getClassMeta()))) {
 							BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
 							if (pMeta == null) {
-								onUnknownProperty(session, currAttr, m, currAttrLine, currAttrCol);
+								session.onUnknownProperty(currAttr, m, currAttrLine, currAttrCol);
 								parseAnything(session, object(), r.unread(), m.getBean(false), true, null); // Read content anyway to ignore it
 							} else {
 								session.setCurrentProperty(pMeta);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ccac121/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
index 07c4a71..56b8448 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
@@ -18,6 +18,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.parser.*;
 import org.apache.juneau.uon.*;
 
 /**
@@ -134,6 +135,12 @@ public class UrlEncodingParserBuilder extends UonParserBuilder {
 		return this;
 	}
 
+	@Override /* ParserBuilder */
+	public UrlEncodingParserBuilder listener(Class<? extends ParserListener> value) {
+		super.listener(value);
+		return this;
+	}
+
 	@Override /* CoreObjectBuilder */
 	public UrlEncodingParserBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);