Browse Source

Fix NullPointerException when equals or hashCode are called on proxy instance

They look something like this:

java.lang.NullPointerException
	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:88)
	at feign.$Proxy16.equals(Unknown Source)

In  my particular instance, I had a proxy created by Feign registered in a Spring application context,
and it resulted in a NullPointerException on application shutdown.
pull/61/head
David M. Carr 11 years ago
parent
commit
a7128264c8
  1. 3
      CHANGES.md
  2. 20
      core/src/main/java/feign/ReflectiveFeign.java
  3. 20
      core/src/test/java/feign/FeignTest.java

3
CHANGES.md

@ -1,3 +1,6 @@ @@ -1,3 +1,6 @@
### Version 4.4.1
* Fix NullPointerException on calling equals and hashCode.
### Version 4.4
* Support overriding default HostnameVerifier.
* Support GZIP content encoding for request bodies.

20
core/src/main/java/feign/ReflectiveFeign.java

@ -85,6 +85,17 @@ public class ReflectiveFeign extends Feign { @@ -85,6 +85,17 @@ public class ReflectiveFeign extends Feign {
}
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("equals".equals(method.getName())) {
try {
Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
return equals(otherHandler);
} catch (IllegalArgumentException e) {
return false;
}
}
if ("hashCode".equals(method.getName())) {
return hashCode();
}
return methodToHandler.get(method).invoke(args);
}
@ -93,10 +104,15 @@ public class ReflectiveFeign extends Feign { @@ -93,10 +104,15 @@ public class ReflectiveFeign extends Feign {
}
@Override public boolean equals(Object obj) {
if (this == obj)
if (obj == null) {
return false;
}
if (this == obj) {
return true;
if (FeignInvocationHandler.class != obj.getClass())
}
if (FeignInvocationHandler.class != obj.getClass()) {
return false;
}
FeignInvocationHandler that = FeignInvocationHandler.class.cast(obj);
return this.target.equals(that.target);
}

20
core/src/test/java/feign/FeignTest.java

@ -51,6 +51,7 @@ import java.util.concurrent.atomic.AtomicBoolean; @@ -51,6 +51,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import static dagger.Provides.Type.SET;
import static feign.Util.UTF_8;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
@ -135,6 +136,10 @@ public class FeignTest { @@ -135,6 +136,10 @@ public class FeignTest {
}
}
interface OtherTestInterface {
@RequestLine("POST /") String post();
}
@Test
public void observableVoid() throws IOException, InterruptedException {
final MockWebServer server = new MockWebServer();
@ -629,4 +634,19 @@ public class FeignTest { @@ -629,4 +634,19 @@ public class FeignTest {
server.shutdown();
}
}
@Test public void equalsAndHashCodeWork() {
TestInterface i1 = Feign.create(TestInterface.class, "http://localhost:8080", new TestInterface.Module());
TestInterface i2 = Feign.create(TestInterface.class, "http://localhost:8080", new TestInterface.Module());
TestInterface i3 = Feign.create(TestInterface.class, "http://localhost:8888", new TestInterface.Module());
OtherTestInterface i4 = Feign.create(OtherTestInterface.class, "http://localhost:8080");
assertTrue(i1.equals(i1));
assertTrue(i1.equals(i2));
assertFalse(i1.equals(i3));
assertFalse(i1.equals(i4));
assertEquals(i1.hashCode(), i1.hashCode());
assertEquals(i1.hashCode(), i2.hashCode());
}
}

Loading…
Cancel
Save