Merge pull request #300 from aguibert/serialize-improve-err-msg

Include property name when serialization fails
diff --git a/README.md b/README.md
index b599345..c6d7f2e 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,10 @@
+# Eclipse Yasson
+
+[![Maven Central](https://img.shields.io/maven-central/v/org.eclipse/yasson.svg?label=Maven%20Central)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.eclipse%22%20a%3A%22yasson%22)
+[![Sonatype Nexus (Snapshots)](https://img.shields.io/nexus/s/https/oss.sonatype.org/org.eclipse/yasson.svg)](https://oss.sonatype.org/content/repositories/snapshots/org/eclipse/yasson/)
 [![Build Status](https://travis-ci.org/eclipse-ee4j/yasson.svg?branch=master)](https://travis-ci.org/eclipse-ee4j/yasson)
 [![License](https://img.shields.io/badge/License-EPL%201.0-green.svg)](https://opensource.org/licenses/EPL-1.0)
-[![Maven Central](https://img.shields.io/maven-central/v/org.eclipse/yasson.svg?label=Maven%20Central)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.eclipse%22%20a%3A%22yasson%22)
 
-# Yasson
 Yasson is a Java framework which provides a standard binding layer between Java classes and JSON documents. This is similar to what JAXB is doing in the XML world. Yasson is an official reference implementation of JSON Binding ([JSR-367](https://jcp.org/en/jsr/detail?id=367)).
 
 It defines a **default mapping** algorithm for converting existing Java classes to JSON suitable for the most cases:
diff --git a/src/main/java/org/eclipse/yasson/YassonProperties.java b/src/main/java/org/eclipse/yasson/YassonProperties.java
index 10e6129..a02b934 100644
--- a/src/main/java/org/eclipse/yasson/YassonProperties.java
+++ b/src/main/java/org/eclipse/yasson/YassonProperties.java
@@ -31,7 +31,7 @@
      * This will made available to parse patterns like yyyy.MM.dd to
      * {@link java.util.Date}, {@link java.util.Calendar}, {@link java.time.Instant} {@link java.time.LocalDate}
      * or even {@link java.time.ZonedDateTime}.
-     * <p>If time zone is not set in the pattern than UTC time zone is used.
+     * <p>If time zone is not set in the pattern then UTC time zone is used.
      * So for example json value 2018.01.01 becomes 2018.01.01 00:00:00 UTC when parsed
      * to instant {@link java.time.Instant} or {@link java.time.ZonedDateTime}.
      */
@@ -39,7 +39,7 @@
 
     /**
      * Serializer to use when object provided to {@link javax.json.bind.Jsonb#toJson(Object)} is {@code null} or an empty
-     * Optional. Much be instance of {@link javax.json.bind.serializer.JsonbSerializer}{@code <Object>}. Its obj value
+     * Optional. Must be instance of {@link javax.json.bind.serializer.JsonbSerializer}{@code <Object>}. Its obj value
      * will be respective parameter.
      */
     public static final String NULL_ROOT_SERIALIZER = "yasson.null-root-serializer";
diff --git a/src/main/java/org/eclipse/yasson/internal/ClassParser.java b/src/main/java/org/eclipse/yasson/internal/ClassParser.java
index 832a99f..2edcfc2 100644
--- a/src/main/java/org/eclipse/yasson/internal/ClassParser.java
+++ b/src/main/java/org/eclipse/yasson/internal/ClassParser.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -29,6 +29,7 @@
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
@@ -173,7 +174,7 @@
         for (Method method : declaredMethods) {
             String name = method.getName();
             //isBridge method filters out methods inherited from interfaces
-            if (!isPropertyMethod(method) || method.isBridge()) {
+            if (!isPropertyMethod(method) || method.isBridge() || isSpecialCaseMethod(clazz, method)) {
                 continue;
             }
             final String propertyName = toPropertyMethod(name);
@@ -181,6 +182,25 @@
             Property property = registerMethod(propertyName, method, classElement, classProperties);
         }
     }
+    
+    /**
+     * Filter out certain methods that get forcibly added to some classes.
+     * For example the public groovy.lang.MetaClass X.getMetaClass() method from Groovy classes
+     */
+    private boolean isSpecialCaseMethod(Class<?> clazz, Method m) {
+        if (!Modifier.isPublic(m.getModifiers()) || Modifier.isStatic(m.getModifiers()) || m.isSynthetic())
+            return false;
+        // Groovy objects will have public groovy.lang.MetaClass X.getMetaClass()
+        // which causes an infinite loop in serialization
+        if (m.getName().equals("getMetaClass") && 
+                m.getReturnType().getCanonicalName().equals("groovy.lang.MetaClass"))
+            return true;
+        // WELD proxy objects will have 'public org.jboss.weld
+        if (m.getName().equals("getMetadata") && 
+                m.getReturnType().getCanonicalName().equals("org.jboss.weld.proxy.WeldClientProxy$Metadata"))
+            return true;
+        return false;
+    }
 
     private boolean isGetter(Method m) {
         return (m.getName().startsWith(GET_PREFIX) || m.getName().startsWith(IS_PREFIX)) && m.getParameterCount() == 0;
diff --git a/src/test/java/org/eclipse/yasson/customization/JsonbPropertyTest.java b/src/test/java/org/eclipse/yasson/customization/JsonbPropertyTest.java
index e35ed1a..4a350b6 100644
--- a/src/test/java/org/eclipse/yasson/customization/JsonbPropertyTest.java
+++ b/src/test/java/org/eclipse/yasson/customization/JsonbPropertyTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -152,6 +152,22 @@
         }
 
     }
+    
+    @Test
+    public void testConflictingWithLowercaseStrategy() {
+    	// scenario raised by user here: https://github.com/eclipse-ee4j/yasson/issues/296
+    	Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE_WITH_UNDERSCORES));
+    	assertEquals("{\"url\":\"http://foo.com\"}", 
+    			jsonb.toJson(new ConflictingIfLowercase()));
+    }
+    
+    public static class ConflictingIfLowercase {
+    	private String url = "foo.com";
+    	
+    	public String getURL() {
+    		return "http://" + url;
+    	}
+    }
 
     public static class NonConflictingProperties {
         private String doi;