Skip to content

Commit d4f3f22

Browse files
committed
Fix #13
1 parent 131fda0 commit d4f3f22

File tree

7 files changed

+178
-59
lines changed

7 files changed

+178
-59
lines changed

paranamer/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ to introspect names of constructor (and factory method) parameters.
7575
</plugin>
7676

7777
<plugin>
78-
<!-- We will shade ASM, to simplify deployment, avoid version conflicts -->
78+
<!-- We will shade Paranamer, to simplify deployment, avoid version conflicts -->
7979
<groupId>org.apache.maven.plugins</groupId>
8080
<artifactId>maven-shade-plugin</artifactId>
8181
<version>${version.plugin.shade}</version>

paranamer/src/main/java/com/fasterxml/jackson/module/paranamer/ParanamerAnnotationIntrospector.java

+22-30
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
package com.fasterxml.jackson.module.paranamer;
22

3-
import java.lang.reflect.AccessibleObject;
4-
import java.lang.reflect.AnnotatedElement;
5-
63
import com.fasterxml.jackson.databind.*;
74
import com.fasterxml.jackson.databind.introspect.Annotated;
85
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
@@ -21,16 +18,27 @@ public class ParanamerAnnotationIntrospector
2118
{
2219
private static final long serialVersionUID = 1;
2320

24-
protected final Paranamer _paranamer;
21+
/**
22+
* Wrapper used to encapsulate actual Paranamer call, to allow serialization
23+
* of this introspector
24+
*/
25+
protected final SerializableParanamer _paranamer;
2526

2627
public ParanamerAnnotationIntrospector() {
27-
this(new CachingParanamer(new BytecodeReadingParanamer()));
28+
this(new SerializableParanamer());
2829
}
2930

30-
public ParanamerAnnotationIntrospector(Paranamer pn) {
31+
/**
32+
* @since 2.7.6
33+
*/
34+
public ParanamerAnnotationIntrospector(SerializableParanamer pn) {
3135
_paranamer = pn;
3236
}
3337

38+
public ParanamerAnnotationIntrospector(Paranamer pn) {
39+
this(new SerializableParanamer(pn));
40+
}
41+
3442
@Override
3543
public PropertyName findNameForDeserialization(Annotated a)
3644
{
@@ -39,10 +47,13 @@ public PropertyName findNameForDeserialization(Annotated a)
3947
* in {@link #findParameterSourceName(AnnotatedParameter)}.
4048
*/
4149
/*
42-
if (a instanceof AnnotatedParameter) {
43-
String rawName = _findParaName((AnnotatedParameter) a);
44-
if (rawName != null) {
45-
return new PropertyName(rawName);
50+
PropertyName name = super.findNameForDeserialization(a);
51+
if (name == null) {
52+
if (a instanceof AnnotatedParameter) {
53+
String rawName _paranamer.findParameterName((AnnotatedParameter) a);
54+
if (rawName != null) {
55+
return new PropertyName(rawName);
56+
}
4657
}
4758
}
4859
*/
@@ -53,26 +64,7 @@ public PropertyName findNameForDeserialization(Annotated a)
5364
@Override
5465
public String findImplicitPropertyName(AnnotatedMember param) {
5566
if (param instanceof AnnotatedParameter) {
56-
return _findParaName((AnnotatedParameter) param);
57-
}
58-
return null;
59-
}
60-
61-
/*
62-
/**********************************************************
63-
/* Internal methods
64-
/**********************************************************
65-
*/
66-
67-
protected String _findParaName(AnnotatedParameter param)
68-
{
69-
int index = param.getIndex();
70-
AnnotatedElement ctor = param.getOwner().getAnnotated();
71-
String[] names = _paranamer.lookupParameterNames((AccessibleObject) ctor, false);
72-
if (names != null) {
73-
if (index < names.length) {
74-
return names[index];
75-
}
67+
return _paranamer.findParameterName((AnnotatedParameter) param);
7668
}
7769
return null;
7870
}

paranamer/src/main/java/com/fasterxml/jackson/module/paranamer/ParanamerOnJacksonAnnotationIntrospector.java

+20-27
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package com.fasterxml.jackson.module.paranamer;
22

3-
import java.lang.reflect.*;
4-
5-
import com.thoughtworks.paranamer.BytecodeReadingParanamer;
6-
import com.thoughtworks.paranamer.CachingParanamer;
73
import com.thoughtworks.paranamer.Paranamer;
84
import com.fasterxml.jackson.databind.AnnotationIntrospector;
95
import com.fasterxml.jackson.databind.PropertyName;
@@ -21,16 +17,31 @@ public class ParanamerOnJacksonAnnotationIntrospector
2117
{
2218
private static final long serialVersionUID = 1;
2319

24-
protected final Paranamer _paranamer;
20+
/**
21+
* Wrapper used to encapsulate actual Paranamer call, to allow serialization
22+
* of this introspector
23+
*/
24+
protected final SerializableParanamer _paranamer;
2525

2626
public ParanamerOnJacksonAnnotationIntrospector() {
27-
this(new CachingParanamer(new BytecodeReadingParanamer()));
27+
this(new SerializableParanamer());
2828
}
2929

30-
public ParanamerOnJacksonAnnotationIntrospector(Paranamer pn) {
30+
/**
31+
* @since 2.7.6
32+
*/
33+
public ParanamerOnJacksonAnnotationIntrospector(SerializableParanamer pn) {
3134
_paranamer = pn;
3235
}
3336

37+
/**
38+
* @deprecated since 2.7.6
39+
*/
40+
@Deprecated
41+
public ParanamerOnJacksonAnnotationIntrospector(Paranamer pn) {
42+
this(new SerializableParanamer(pn));
43+
}
44+
3445
@Override
3546
public PropertyName findNameForDeserialization(Annotated a)
3647
{
@@ -42,7 +53,7 @@ public PropertyName findNameForDeserialization(Annotated a)
4253
PropertyName name = super.findNameForDeserialization(a);
4354
if (name == null) {
4455
if (a instanceof AnnotatedParameter) {
45-
String rawName = _findParaName((AnnotatedParameter) a);
56+
String rawName _paranamer.findParameterName((AnnotatedParameter) a);
4657
if (rawName != null) {
4758
return new PropertyName(rawName);
4859
}
@@ -52,28 +63,10 @@ public PropertyName findNameForDeserialization(Annotated a)
5263
return null;
5364
}
5465

55-
// since 2.4
5666
@Override
5767
public String findImplicitPropertyName(AnnotatedMember param) {
5868
if (param instanceof AnnotatedParameter) {
59-
return _findParaName((AnnotatedParameter) param);
60-
}
61-
return null;
62-
}
63-
64-
/*
65-
/**********************************************************
66-
/* Internal methods
67-
/**********************************************************
68-
*/
69-
70-
protected String _findParaName(AnnotatedParameter param)
71-
{
72-
int index = param.getIndex();
73-
AnnotatedElement ctor = param.getOwner().getAnnotated();
74-
String[] names = _paranamer.lookupParameterNames((AccessibleObject) ctor);
75-
if (names != null && index < names.length) {
76-
return names[index];
69+
return _paranamer.findParameterName((AnnotatedParameter) param);
7770
}
7871
return null;
7972
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.fasterxml.jackson.module.paranamer;
2+
3+
import java.lang.reflect.AccessibleObject;
4+
import java.lang.reflect.AnnotatedElement;
5+
6+
import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
7+
import com.thoughtworks.paranamer.BytecodeReadingParanamer;
8+
import com.thoughtworks.paranamer.CachingParanamer;
9+
import com.thoughtworks.paranamer.Paranamer;
10+
11+
/**
12+
* Simple wrapper used to hide the fact that paranamer accessor itself if not JDK serializable
13+
* in a way to keep actual <code>ObjectMapper</code> / <code>ObjectReader</code> serializable.
14+
*/
15+
public class SerializableParanamer
16+
implements java.io.Serializable
17+
{
18+
private static final long serialVersionUID = 1L;
19+
20+
protected transient Paranamer _paranamer;
21+
22+
public SerializableParanamer() {
23+
this(null);
24+
}
25+
26+
public SerializableParanamer(Paranamer paranamer) {
27+
if (paranamer == null) {
28+
paranamer = defaultParanamer();
29+
}
30+
_paranamer = paranamer;
31+
}
32+
33+
/**
34+
* Overridable method in case someone really wants to sub-class this implementation.
35+
*/
36+
protected Paranamer defaultParanamer() {
37+
return new CachingParanamer(new BytecodeReadingParanamer());
38+
}
39+
40+
/*
41+
/**********************************************************
42+
/* Public API
43+
/**********************************************************
44+
*/
45+
46+
public String findParameterName(AnnotatedParameter param)
47+
{
48+
int index = param.getIndex();
49+
AnnotatedElement ctor = param.getOwner().getAnnotated();
50+
String[] names = _paranamer.lookupParameterNames((AccessibleObject) ctor, false);
51+
if (names != null && index < names.length) {
52+
return names[index];
53+
}
54+
return null;
55+
}
56+
57+
/*
58+
/**********************************************************
59+
/* JDK serialization handling
60+
/**********************************************************
61+
*/
62+
63+
Object readResolve() {
64+
_paranamer = defaultParanamer();
65+
return this;
66+
}
67+
}

paranamer/src/test/java/com/fasterxml/jackson/module/paranamer/SimpleTest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ public void testSimple() throws Exception
5050
assertEquals(40, bean.age);
5151
}
5252

53-
// As per [Issue#3]
53+
// Let's test handling of case where parameter names are not found; for example when
54+
// trying to access things for JDK types
5455
public void testWrapper() throws Exception
5556
{
5657
ObjectMapper mapper = new ObjectMapper().registerModule(new ParanamerModule());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.fasterxml.jackson.module.paranamer;
2+
3+
import java.io.ByteArrayInputStream;
4+
import java.io.ByteArrayOutputStream;
5+
import java.io.IOException;
6+
import java.io.ObjectInputStream;
7+
import java.io.ObjectOutputStream;
8+
9+
import com.fasterxml.jackson.databind.ObjectMapper;
10+
11+
public class TestJDKSerializability extends ParanamerTestBase
12+
{
13+
static class Point {
14+
public int x, y;
15+
}
16+
17+
public void testMapper() throws Exception
18+
{
19+
ObjectMapper mapper = new ObjectMapper().registerModule(new ParanamerModule());
20+
// first: serialize as is
21+
byte[] ser = jdkSerialize(mapper);
22+
ObjectMapper m2 = jdkDeserialize(ser);
23+
24+
// then use lightly, repeat
25+
byte[] rawPoint = m2.writeValueAsBytes(new Point());
26+
Point result = m2.readValue(rawPoint, Point.class);
27+
assertNotNull(result);
28+
29+
ser = jdkSerialize(m2);
30+
ObjectMapper m3 = jdkDeserialize(ser);
31+
assertNotNull(m3);
32+
}
33+
34+
/*
35+
/**********************************************************
36+
/* Helper methods
37+
/**********************************************************
38+
*/
39+
40+
protected byte[] jdkSerialize(Object o) throws IOException
41+
{
42+
ByteArrayOutputStream bytes = new ByteArrayOutputStream(1000);
43+
ObjectOutputStream obOut = new ObjectOutputStream(bytes);
44+
obOut.writeObject(o);
45+
obOut.close();
46+
return bytes.toByteArray();
47+
}
48+
49+
@SuppressWarnings("unchecked")
50+
protected <T> T jdkDeserialize(byte[] raw) throws IOException
51+
{
52+
ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(raw));
53+
try {
54+
return (T) objIn.readObject();
55+
} catch (ClassNotFoundException e) {
56+
fail("Missing class: "+e.getMessage());
57+
return null;
58+
} finally {
59+
objIn.close();
60+
}
61+
}
62+
}

release-notes/VERSION

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ Modules:
88
=== Releases ===
99
------------------------------------------------------------------------
1010

11+
2.7.6 (not yet released)
12+
13+
#13: (paranamer) Make `ParanamerAnnotationIntrospector` serializable
14+
1115
2.7.5 (11-Jun-2016)
1216

1317
No changes since 2.7.4

0 commit comments

Comments
 (0)