Do not share interceptors between individual interface based client
instances Conflicts: src/changes/changes.xml
This commit is contained in:
parent
d757bc1f16
commit
84c08b1684
|
@ -22,47 +22,28 @@ package ca.uhn.fhir.rest.client;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.http.client.HttpClient;
|
import org.apache.http.client.HttpClient;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
import ca.uhn.fhir.rest.client.ClientInvocationHandlerFactory.ILambda;
|
||||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
|
||||||
|
|
||||||
public class ClientInvocationHandler extends BaseClient implements InvocationHandler {
|
class ClientInvocationHandler extends BaseClient implements InvocationHandler {
|
||||||
|
|
||||||
private final Map<Method, BaseMethodBinding<?>> myBindings = new HashMap<Method, BaseMethodBinding<?>>();
|
|
||||||
|
|
||||||
private final Map<Method, ILambda> myMethodToLambda = new HashMap<Method, ILambda>();
|
|
||||||
|
|
||||||
private final Map<Method, Object> myMethodToReturnValue = new HashMap<Method, Object>();
|
|
||||||
|
|
||||||
|
private final Map<Method, BaseMethodBinding<?>> myBindings;
|
||||||
|
private final Map<Method, Object> myMethodToReturnValue;
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
|
private Map<Method, ILambda> myMethodToLambda;
|
||||||
|
|
||||||
public ClientInvocationHandler(HttpClient theClient, FhirContext theContext, String theUrlBase, Class<? extends IRestfulClient> theClientType) {
|
public ClientInvocationHandler(HttpClient theClient, FhirContext theContext, String theUrlBase, Map<Method, Object> theMethodToReturnValue, Map<Method, BaseMethodBinding<?>> theBindings, Map<Method, ILambda> theMethodToLambda) {
|
||||||
super(theClient, theUrlBase);
|
super(theClient, theUrlBase);
|
||||||
|
|
||||||
myContext =theContext;
|
myContext =theContext;
|
||||||
|
myMethodToReturnValue = theMethodToReturnValue;
|
||||||
try {
|
myBindings = theBindings;
|
||||||
myMethodToReturnValue.put(theClientType.getMethod("getFhirContext"), theContext);
|
myMethodToLambda=theMethodToLambda;
|
||||||
myMethodToReturnValue.put(theClientType.getMethod("getHttpClient"), theClient);
|
|
||||||
myMethodToReturnValue.put(theClientType.getMethod("getServerBase"), theUrlBase);
|
|
||||||
|
|
||||||
myMethodToLambda.put(theClientType.getMethod("setEncoding", EncodingEnum.class), new SetEncodingLambda());
|
|
||||||
myMethodToLambda.put(theClientType.getMethod("setPrettyPrint", boolean.class), new SetPrettyPrintLambda());
|
|
||||||
myMethodToLambda.put(theClientType.getMethod("registerInterceptor", IClientInterceptor.class), new RegisterInterceptorLambda());
|
|
||||||
myMethodToLambda.put(theClientType.getMethod("unregisterInterceptor", IClientInterceptor.class), new UnregisterInterceptorLambda());
|
|
||||||
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
throw new ConfigurationException("Failed to find methods on client. This is a HAPI bug!", e);
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
throw new ConfigurationException("Failed to find methods on client. This is a HAPI bug!", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBinding(Method theMethod, BaseMethodBinding<?> theBinding) {
|
public void addBinding(Method theMethod, BaseMethodBinding<?> theBinding) {
|
||||||
|
@ -84,49 +65,11 @@ public class ClientInvocationHandler extends BaseClient implements InvocationHan
|
||||||
|
|
||||||
ILambda lambda = myMethodToLambda.get(theMethod);
|
ILambda lambda = myMethodToLambda.get(theMethod);
|
||||||
if (lambda != null) {
|
if (lambda != null) {
|
||||||
return lambda.handle(theArgs);
|
return lambda.handle(this, theArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnsupportedOperationException("The method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getSimpleName() + " has no handler. Did you forget to annotate it with a RESTful method annotation?");
|
throw new UnsupportedOperationException("The method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getSimpleName() + " has no handler. Did you forget to annotate it with a RESTful method annotation?");
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface ILambda {
|
|
||||||
Object handle(Object[] theArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SetEncodingLambda implements ILambda {
|
|
||||||
@Override
|
|
||||||
public Object handle(Object[] theArgs) {
|
|
||||||
EncodingEnum encoding = (EncodingEnum) theArgs[0];
|
|
||||||
setEncoding(encoding);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SetPrettyPrintLambda implements ILambda {
|
|
||||||
@Override
|
|
||||||
public Object handle(Object[] theArgs) {
|
|
||||||
Boolean prettyPrint = (Boolean) theArgs[0];
|
|
||||||
setPrettyPrint(prettyPrint);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private class UnregisterInterceptorLambda implements ILambda {
|
|
||||||
@Override
|
|
||||||
public Object handle(Object[] theArgs) {
|
|
||||||
IClientInterceptor interceptor = (IClientInterceptor) theArgs[0];
|
|
||||||
unregisterInterceptor(interceptor);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class RegisterInterceptorLambda implements ILambda {
|
|
||||||
@Override
|
|
||||||
public Object handle(Object[] theArgs) {
|
|
||||||
IClientInterceptor interceptor = (IClientInterceptor) theArgs[0];
|
|
||||||
registerInterceptor(interceptor);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
package ca.uhn.fhir.rest.client;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Core Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 University Health Network
|
||||||
|
* %%
|
||||||
|
* Licensed 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.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||||
|
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||||
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
|
|
||||||
|
class ClientInvocationHandlerFactory {
|
||||||
|
|
||||||
|
private final Map<Method, BaseMethodBinding<?>> myBindings = new HashMap<Method, BaseMethodBinding<?>>();
|
||||||
|
private final Map<Method, Object> myMethodToReturnValue = new HashMap<Method, Object>();
|
||||||
|
private final Map<Method, ILambda> myMethodToLambda = new HashMap<Method, ILambda>();
|
||||||
|
private final FhirContext myContext;
|
||||||
|
private final HttpClient myClient;
|
||||||
|
private final String myUrlBase;
|
||||||
|
|
||||||
|
public ClientInvocationHandlerFactory(HttpClient theClient, FhirContext theContext, String theUrlBase, Class<? extends IRestfulClient> theClientType) {
|
||||||
|
myClient = theClient;
|
||||||
|
myUrlBase = theUrlBase;
|
||||||
|
myContext = theContext;
|
||||||
|
|
||||||
|
try {
|
||||||
|
myMethodToReturnValue.put(theClientType.getMethod("getFhirContext"), theContext);
|
||||||
|
myMethodToReturnValue.put(theClientType.getMethod("getHttpClient"), theClient);
|
||||||
|
myMethodToReturnValue.put(theClientType.getMethod("getServerBase"), theUrlBase);
|
||||||
|
|
||||||
|
myMethodToLambda.put(theClientType.getMethod("setEncoding", EncodingEnum.class), new SetEncodingLambda());
|
||||||
|
myMethodToLambda.put(theClientType.getMethod("setPrettyPrint", boolean.class), new SetPrettyPrintLambda());
|
||||||
|
myMethodToLambda.put(theClientType.getMethod("registerInterceptor", IClientInterceptor.class), new RegisterInterceptorLambda());
|
||||||
|
myMethodToLambda.put(theClientType.getMethod("unregisterInterceptor", IClientInterceptor.class), new UnregisterInterceptorLambda());
|
||||||
|
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new ConfigurationException("Failed to find methods on client. This is a HAPI bug!", e);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
throw new ConfigurationException("Failed to find methods on client. This is a HAPI bug!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addBinding(Method theMethod, BaseMethodBinding<?> theBinding) {
|
||||||
|
myBindings.put(theMethod, theBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientInvocationHandler newInvocationHandler() {
|
||||||
|
return new ClientInvocationHandler(myClient, myContext, myUrlBase, myMethodToReturnValue, myBindings, myMethodToLambda);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ILambda {
|
||||||
|
Object handle(ClientInvocationHandler theTarget, Object[] theArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetEncodingLambda implements ILambda {
|
||||||
|
@Override
|
||||||
|
public Object handle(ClientInvocationHandler theTarget, Object[] theArgs) {
|
||||||
|
EncodingEnum encoding = (EncodingEnum) theArgs[0];
|
||||||
|
theTarget.setEncoding(encoding);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetPrettyPrintLambda implements ILambda {
|
||||||
|
@Override
|
||||||
|
public Object handle(ClientInvocationHandler theTarget, Object[] theArgs) {
|
||||||
|
Boolean prettyPrint = (Boolean) theArgs[0];
|
||||||
|
theTarget.setPrettyPrint(prettyPrint);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnregisterInterceptorLambda implements ILambda {
|
||||||
|
@Override
|
||||||
|
public Object handle(ClientInvocationHandler theTarget, Object[] theArgs) {
|
||||||
|
IClientInterceptor interceptor = (IClientInterceptor) theArgs[0];
|
||||||
|
theTarget.unregisterInterceptor(interceptor);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RegisterInterceptorLambda implements ILambda {
|
||||||
|
@Override
|
||||||
|
public Object handle(ClientInvocationHandler theTarget, Object[] theArgs) {
|
||||||
|
IClientInterceptor interceptor = (IClientInterceptor) theArgs[0];
|
||||||
|
theTarget.registerInterceptor(interceptor);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -44,7 +44,7 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
||||||
private int myConnectTimeout = 10000;
|
private int myConnectTimeout = 10000;
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
private HttpClient myHttpClient;
|
private HttpClient myHttpClient;
|
||||||
private Map<Class<? extends IRestfulClient>, ClientInvocationHandler> myInvocationHandlers = new HashMap<Class<? extends IRestfulClient>, ClientInvocationHandler>();
|
private Map<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory> myInvocationHandlers = new HashMap<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory>();
|
||||||
private int mySocketTimeout = 10000;
|
private int mySocketTimeout = 10000;
|
||||||
private HttpHost myProxy;
|
private HttpHost myProxy;
|
||||||
|
|
||||||
|
@ -146,9 +146,9 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
||||||
serverBase = serverBase + "/";
|
serverBase = serverBase + "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientInvocationHandler invocationHandler = myInvocationHandlers.get(theClientType);
|
ClientInvocationHandlerFactory invocationHandler = myInvocationHandlers.get(theClientType);
|
||||||
if (invocationHandler == null) {
|
if (invocationHandler == null) {
|
||||||
invocationHandler = new ClientInvocationHandler(client, myContext, serverBase, theClientType);
|
invocationHandler = new ClientInvocationHandlerFactory(client, myContext, serverBase, theClientType);
|
||||||
for (Method nextMethod : theClientType.getMethods()) {
|
for (Method nextMethod : theClientType.getMethods()) {
|
||||||
BaseMethodBinding<?> binding = BaseMethodBinding.bindMethod(nextMethod, myContext, null);
|
BaseMethodBinding<?> binding = BaseMethodBinding.bindMethod(nextMethod, myContext, null);
|
||||||
invocationHandler.addBinding(nextMethod, binding);
|
invocationHandler.addBinding(nextMethod, binding);
|
||||||
|
@ -156,7 +156,7 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
||||||
myInvocationHandlers.put(theClientType, invocationHandler);
|
myInvocationHandlers.put(theClientType, invocationHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
T proxy = instantiateProxy(theClientType, invocationHandler);
|
T proxy = instantiateProxy(theClientType, invocationHandler.newInvocationHandler());
|
||||||
|
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,8 +75,23 @@ public class BasicAuthInterceptorTest {
|
||||||
client.registerInterceptor(new BasicAuthInterceptor("myuser", "mypass"));
|
client.registerInterceptor(new BasicAuthInterceptor("myuser", "mypass"));
|
||||||
client.getPatientById(new IdDt("111"));
|
client.getPatientById(new IdDt("111"));
|
||||||
|
|
||||||
HttpUriRequest req = capt.getValue();
|
assertEquals(1, capt.getAllValues().size());
|
||||||
|
HttpUriRequest req = capt.getAllValues().get(0);
|
||||||
|
assertEquals(1, req.getHeaders("Authorization").length);
|
||||||
assertEquals("Basic bXl1c2VyOm15cGFzcw==", req.getFirstHeader("Authorization").getValue());
|
assertEquals("Basic bXl1c2VyOm15cGFzcw==", req.getFirstHeader("Authorization").getValue());
|
||||||
|
|
||||||
|
// Create a second client and make sure we get the same results
|
||||||
|
|
||||||
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||||
|
client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||||
|
client.registerInterceptor(new BasicAuthInterceptor("myuser", "mypass"));
|
||||||
|
client.getPatientById(new IdDt("111"));
|
||||||
|
|
||||||
|
assertEquals(2, capt.getAllValues().size());
|
||||||
|
req = capt.getAllValues().get(1);
|
||||||
|
assertEquals(1, req.getHeaders("Authorization").length);
|
||||||
|
assertEquals("Basic bXl1c2VyOm15cGFzcw==", req.getFirstHeader("Authorization").getValue());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
|
</classpath>
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>hapi-fhir-example-simple-server</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.wst.common.project.facet.core.builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.wst.validation.validationbuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
|
||||||
|
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
|
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
|
||||||
|
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
|
@ -126,6 +126,38 @@
|
||||||
"[base url]/Patient/123" but if the RP returns ID "http://foo/Patient/123" the ID will be
|
"[base url]/Patient/123" but if the RP returns ID "http://foo/Patient/123" the ID will be
|
||||||
returned exactly as is. Thanks to Bill de Beaubien for the suggestion!
|
returned exactly as is. Thanks to Bill de Beaubien for the suggestion!
|
||||||
</action>
|
</action>
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
<action type="fix" issue="55">
|
||||||
|
JPA module Transaction operation was not correctly replacing logical IDs
|
||||||
|
beginning with "cid:" with server assigned IDs, as required by the
|
||||||
|
specification.
|
||||||
|
</action>
|
||||||
|
<action type="fix" dev="tahurac">
|
||||||
|
<![CDATA[FhirTerser]]> did not visit or find children in contained resources when
|
||||||
|
searching a resource. This caused server implementations to not always return contained
|
||||||
|
resources when they are included with a resource being returned.
|
||||||
|
</action>
|
||||||
|
<action type="add" dev="lmds">
|
||||||
|
Add a method <![CDATA[String IResource#getResourceName()]]> which returns the name of the
|
||||||
|
resource in question (e.g. "Patient", or "Observation"). This is intended as a
|
||||||
|
convenience to users.
|
||||||
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
Do not strip version from resource references in resources returned
|
||||||
|
from server search methods. Thanks to Bill de Beaubien for reporting!
|
||||||
|
</action>
|
||||||
|
<action type="fix" dev="jjathman" issue="54">
|
||||||
|
Correct an issue with the validator where changes to the underlying
|
||||||
|
OperationOutcome produced by a validation cycle cause the validation
|
||||||
|
results to be incorrect.
|
||||||
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
Client interceptors registered to an interface based client instance
|
||||||
|
were applied to other client instances for the same client interface as well. (Issue
|
||||||
|
did not affect generic/fluent clients)
|
||||||
|
</action>
|
||||||
|
>>>>>>> 51f2ce1... Do not share interceptors between individual interface based client
|
||||||
</release>
|
</release>
|
||||||
<release version="0.7" date="2014-Oct-23">
|
<release version="0.7" date="2014-Oct-23">
|
||||||
<action type="add" issue="30">
|
<action type="add" issue="30">
|
||||||
|
|
Loading…
Reference in New Issue