Skip to content

Commit

Permalink
Fix/payara4003 Inaccessible constructor with @ConstructorProperties (#…
Browse files Browse the repository at this point in the history
…280)

* Support for @ConstructorProperties as proposed in jsonb-api/issues/115

jakartaee/jsonb-api#115 (comment)

Signed-off-by: Johannes <johnnyt@gmx.at>

* Added missing final keywords. Flag for generic serializers/adapters moved to ComponentMatcher.

Signed-off-by: Roman Grigoriadi <roman.grigoriadi@oracle.com>

* Update module-info.java

Added required module for ConstructorProperties-Annotation

Signed-off-by: Johannes <johnnyt@gmx.at>

* Update pom.xml

Added required module for ConstructorProperties-Annotation

Signed-off-by: Johannes <johnnyt@gmx.at>

* formatting

Signed-off-by: Johannes <johnnyt@gmx.at>

* Merged changes from original repository

Signed-off-by: Johannes <johnnyt@gmx.at>

* Support for @ConstructorProperties as proposed in jsonb-api/issues/115

Signed-off-by: Johannes <johnnyt@gmx.at>

* Add builtin serializer for java.sql.Timestamp

* Further tests, reset formatting

Signed-off-by: Johannes <johnnyt@gmx.at>

* fix for payara/Payara#4003

Signed-off-by: Johannes <johnnyt@gmx.at>

* test fixture names reverted back

Signed-off-by: Johannes <johnnyt@gmx.at>

* Added one currently ignored unit test for discussion

Signed-off-by: Johannes <johnnyt@gmx.at>

* removed message key for info log.

Signed-off-by: Johannes <johnnyt@gmx.at>
  • Loading branch information
JohT authored and aguibert committed Sep 5, 2019
1 parent 56f7f0b commit 09d7a24
Show file tree
Hide file tree
Showing 5 changed files with 292 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
import org.eclipse.yasson.internal.model.JsonbCreator;
import org.eclipse.yasson.internal.properties.MessageKeys;
import org.eclipse.yasson.internal.properties.Messages;
import org.eclipse.yasson.spi.JsonbComponentInstanceCreator;

import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.logging.Logger;

class ConstructorPropertiesAnnotationIntrospector {

private static final Logger LOG = Logger.getLogger(JsonbComponentInstanceCreator.class.getName());
private static final Logger LOG = Logger.getLogger(ConstructorPropertiesAnnotationIntrospector.class.getName());

private final JsonbContext jsonbContext;
private final AnnotationFinder constructorProperties;
Expand Down Expand Up @@ -43,6 +44,12 @@ public JsonbCreator getCreator(Constructor<?>[] constructors) {
if (!(properties instanceof String[])) {
continue;
}
if (!Modifier.isPublic(constructor.getModifiers())) {
String declaringClass = constructor.getDeclaringClass().getName();
String message = "The constructor of {0} annotated with @ConstructorProperties {1} is not accessible and will be ignored.";
LOG.finest(String.format(message, declaringClass, Arrays.toString((String[]) properties)));
continue;
}
if (jsonbCreator != null) {
// don't fail in this case, because it is perfectly allowed to have more than one
// @ConstructorProperties-Annotation in general.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@
import org.eclipse.yasson.internal.AnnotationIntrospectorTestFixtures.ObjectWithJsonbCreatorAndConstructorPropertiesAnnotation;
import org.eclipse.yasson.internal.AnnotationIntrospectorTestFixtures.ObjectWithJsonbCreatorAnnotatedConstructor;
import org.eclipse.yasson.internal.AnnotationIntrospectorTestFixtures.ObjectWithJsonbCreatorAnnotatedFactoryMethod;
import org.eclipse.yasson.internal.AnnotationIntrospectorTestFixtures.ObjectWithMissingConstructorAnnotation;
import org.eclipse.yasson.internal.AnnotationIntrospectorTestFixtures.ObjectWithJsonbCreatorAnnotatedProtectedConstructor;
import org.eclipse.yasson.internal.AnnotationIntrospectorTestFixtures.ObjectWithNoArgAndJsonbCreatorAnnotatedProtectedConstructor;
import org.eclipse.yasson.internal.AnnotationIntrospectorTestFixtures.ObjectWithTwoJsonbCreatorAnnotatedSpots;
import org.eclipse.yasson.internal.AnnotationIntrospectorTestFixtures.ObjectWithoutAnnotatedConstructor;
import org.eclipse.yasson.internal.model.JsonbCreator;

import javax.json.bind.JsonbConfig;
import javax.json.bind.JsonbException;

import javax.json.spi.JsonProvider;

import org.hamcrest.core.IsInstanceOf;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
Expand Down Expand Up @@ -59,6 +63,23 @@ public void testObjectShouldBeCreateableFromJsonbAnnotatedStaticFactoryMethodIgn
assertCreatedInstanceContainsAllParameters(ObjectWithJsonbCreatorAndConstructorPropertiesAnnotation.example(), creator);
}

@Test
public void testJsonbAnnotatedProtectedConstructorLeadsToAnException() {
exception.expect(JsonbException.class);
exception.expectCause(IsInstanceOf.instanceOf(IllegalAccessException.class));
JsonbCreator creator = instrospector.getCreator(ObjectWithJsonbCreatorAnnotatedProtectedConstructor.class);
assertCreatedInstanceContainsAllParameters(ObjectWithJsonbCreatorAnnotatedProtectedConstructor.example(), creator);
}

// TODO Under discussion: https://github.com/eclipse-ee4j/yasson/issues/326
@Ignore
@Test
public void testNoArgConstructorShouldBePreferredOverUnusableJsonbAnnotatedProtectedConstructor() {
JsonbCreator creator = instrospector.getCreator(ObjectWithNoArgAndJsonbCreatorAnnotatedProtectedConstructor.class);
assertParameters(ObjectWithNoArgAndJsonbCreatorAnnotatedProtectedConstructor.parameters(), creator);
assertCreatedInstanceContainsAllParameters(ObjectWithNoArgAndJsonbCreatorAnnotatedProtectedConstructor.example(), creator);
}

@Test
public void testMoreThanOneAnnotatedCreatorMethodShouldLeadToAnException() {
exception.expect(JsonbException.class);
Expand All @@ -68,7 +89,7 @@ public void testMoreThanOneAnnotatedCreatorMethodShouldLeadToAnException() {

@Test
public void testCreatorShouldBeNullOnMissingConstructorAnnotation() {
assertNull(instrospector.getCreator(ObjectWithMissingConstructorAnnotation.class));
assertNull(instrospector.getCreator(ObjectWithoutAnnotatedConstructor.class));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ public static final ProvidesParameterRepresentation example() {
return new ObjectWithoutAnnotatedConstructor("a string", Long.MAX_VALUE);
}

@JsonbCreator
public ObjectWithoutAnnotatedConstructor( //
@JsonbProperty("string") String aString, //
@JsonbProperty("primitive") long aPrimitive) {
public ObjectWithoutAnnotatedConstructor(String aString, long aPrimitive) {
this.string = aString;
this.primitive = aPrimitive;
}
Expand Down Expand Up @@ -93,6 +90,88 @@ public String toString() {
}
}

public static class ObjectWithJsonbCreatorAnnotatedProtectedConstructor implements ProvidesParameterRepresentation {
private final String string;
private final long primitive;

public static final Map<String, Type> parameters() {
return twoParameters("string", String.class, "primitive", long.class);
}

public static final ProvidesParameterRepresentation example() {
return new ObjectWithJsonbCreatorAnnotatedProtectedConstructor("a string", Long.MAX_VALUE);
}

@JsonbCreator
protected ObjectWithJsonbCreatorAnnotatedProtectedConstructor( //
@JsonbProperty("string") String aString, //
@JsonbProperty("primitive") long aPrimitive) {
this.string = aString;
this.primitive = aPrimitive;
}

@Override
public Object[] asParameters() {
return new Object[] { string, primitive };
}

@Override
public String toString() {
return "ObjectWithJsonbCreatorAnnotatedProtectedConstructor [string=" + string + ", primitive=" + primitive + "]";
}
}

public static class ObjectWithNoArgAndJsonbCreatorAnnotatedProtectedConstructor implements ProvidesParameterRepresentation {
private String string;
private long primitive;

public static final Map<String, Type> parameters() {
return twoParameters("string", String.class, "primitive", long.class);
}

public static final ProvidesParameterRepresentation example() {
return new ObjectWithNoArgAndJsonbCreatorAnnotatedProtectedConstructor("a string", Long.MAX_VALUE);
}

public ObjectWithNoArgAndJsonbCreatorAnnotatedProtectedConstructor() {
super();
}

@JsonbCreator
protected ObjectWithNoArgAndJsonbCreatorAnnotatedProtectedConstructor( //
@JsonbProperty("string") String aString, //
@JsonbProperty("primitive") long aPrimitive) {
this.string = aString;
this.primitive = aPrimitive;
}

public String getString() {
return string;
}

public void setString(String string) {
this.string = string;
}

public long getPrimitive() {
return primitive;
}

public void setPrimitive(long primitive) {
this.primitive = primitive;
}

@Override
public Object[] asParameters() {
return new Object[] { string, primitive };
}

@Override
public String toString() {
return "ObjectWithNoArgAndJsonbCreatorAnnotatedProtectedConstructor [string=" + string + ", primitive=" + primitive + "]";
}
}

public static class ObjectWithJsonbCreatorAnnotatedFactoryMethod implements ProvidesParameterRepresentation {
private final String string;
private final long primitive;
Expand Down Expand Up @@ -265,6 +344,161 @@ public String toString() {
}
}

public static class ObjectWithPublicNoArgAndAnnotatedPrivateConstructor implements ProvidesParameterRepresentation {
private String string;
private Long primitive;

public static final Map<String, Type> parameters() {
return twoParameters("string", String.class, "primitive", long.class);
}

public static final ProvidesParameterRepresentation example() {
return new ObjectWithPublicNoArgAndAnnotatedPrivateConstructor(" ", Long.valueOf(-12));
}

public ObjectWithPublicNoArgAndAnnotatedPrivateConstructor() {
super();
}

@ConstructorProperties({ "string", "primitive" })
private ObjectWithPublicNoArgAndAnnotatedPrivateConstructor(String aString, long aPrimitive) {
this.string = aString;
this.primitive = aPrimitive;
}

public Long getPrimitive() {
return primitive;
}

public void setPrimitive(Long primitive) {
this.primitive = primitive;
}

public String getString() {
return string;
}

public void setString(String string) {
this.string = string;
}

@Override
public Object[] asParameters() {
return new Object[] { string, primitive };
}

@Override
public String toString() {
return "ObjectWithPublicNoArgAndAnnotatedPrivateConstructor [string=" + string + ", primitive=" + primitive + "]";
}
}

public static class ObjectWithPublicNoArgAndAnnotatedPackageProtectedConstructor implements ProvidesParameterRepresentation {
private String string;
private Long primitive;

public static final Map<String, Type> parameters() {
return twoParameters("string", String.class, "primitive", long.class);
}

public static final ProvidesParameterRepresentation example() {
return new ObjectWithPublicNoArgAndAnnotatedPackageProtectedConstructor(" ", Long.valueOf(-12));
}

public static final ObjectWithPublicNoArgAndAnnotatedPackageProtectedConstructor create(String aString, long aPrimitive) {
return new ObjectWithPublicNoArgAndAnnotatedPackageProtectedConstructor(aString, aPrimitive);
}

public ObjectWithPublicNoArgAndAnnotatedPackageProtectedConstructor() {
super();
}

@ConstructorProperties({ "string", "primitive" })
ObjectWithPublicNoArgAndAnnotatedPackageProtectedConstructor(String aString, long aPrimitive) {
this.string = aString;
this.primitive = aPrimitive;
}

public Long getPrimitive() {
return primitive;
}

public void setPrimitive(Long primitive) {
this.primitive = primitive;
}

public String getString() {
return string;
}

public void setString(String string) {
this.string = string;
}

@Override
public Object[] asParameters() {
return new Object[] { string, primitive };
}

@Override
public String toString() {
return "ObjectWithPublicNoArgAndAnnotatedPackageProtectedConstructor [string=" + string + ", primitive=" + primitive + "]";
}
}

public static class ObjectWithPublicNoArgAndAnnotatedProtectedConstructor implements ProvidesParameterRepresentation {
private String string;
private Long primitive;

public static final Map<String, Type> parameters() {
return twoParameters("string", String.class, "primitive", long.class);
}

public static final ProvidesParameterRepresentation example() {
return new ObjectWithPublicNoArgAndAnnotatedPackageProtectedConstructor(" ", Long.valueOf(-12));
}

public static final ObjectWithPublicNoArgAndAnnotatedProtectedConstructor create(String aString, long aPrimitive) {
return new ObjectWithPublicNoArgAndAnnotatedProtectedConstructor(aString, aPrimitive);
}

@ConstructorProperties({ "string", "primitive" })
protected ObjectWithPublicNoArgAndAnnotatedProtectedConstructor(String aString, long aPrimitive) {
this.string = aString;
this.primitive = aPrimitive;
}

public ObjectWithPublicNoArgAndAnnotatedProtectedConstructor() {
super();
}

public Long getPrimitive() {
return primitive;
}

public void setPrimitive(Long primitive) {
this.primitive = primitive;
}

public String getString() {
return string;
}

public void setString(String string) {
this.string = string;
}

@Override
public Object[] asParameters() {
return new Object[] { string, primitive };
}

@Override
public String toString() {
return "ObjectWithJsonbCreatorAndConstructorPropertiesAnnotation [string=" + string + ", primitive=" + primitive + "]";
}
}

public static class ObjectWithMissingConstructorAnnotation implements ProvidesParameterRepresentation {
private final String string;
private final long primitive;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import org.eclipse.yasson.internal.AnnotationIntrospectorTestFixtures.ObjectWithJsonbCreatorAnnotatedConstructor;
import org.eclipse.yasson.internal.AnnotationIntrospectorTestFixtures.ObjectWithJsonbCreatorAnnotatedFactoryMethod;
import org.eclipse.yasson.internal.AnnotationIntrospectorTestFixtures.ObjectWithMissingConstructorAnnotation;
import org.eclipse.yasson.internal.AnnotationIntrospectorTestFixtures.ObjectWithoutAnnotatedConstructor;
import org.eclipse.yasson.internal.model.JsonbCreator;

import javax.json.bind.JsonbConfig;
Expand Down Expand Up @@ -47,7 +47,7 @@ public void testNoConstructorPropertiesAnnotationWithoutOptionalModules() {

@Test
public void testCreatorShouldBeNullOnMissingConstructorAnnotation() {
assertNull(instrospector.getCreator(ObjectWithMissingConstructorAnnotation.class));
assertNull(instrospector.getCreator(ObjectWithoutAnnotatedConstructor.class));
}

@Test
Expand Down

0 comments on commit 09d7a24

Please sign in to comment.