Skip to content

Commit

Permalink
Adding new Encoder type
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiocarvalho777 committed Jul 7, 2021
1 parent 5c460ae commit 7067d23
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 5 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/feign/DeclarativeContract.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public final List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType)
* (unless they are the same).
*
* @param data metadata collected so far relating to the current java method.
* @param clz the class to process
* @param targetType the class to process

This comment has been minimized.

Copy link
@fabiocarvalho777

fabiocarvalho777 Jul 7, 2021

Author Owner

Just a small javadoc fix

*/
@Override
protected final void processAnnotationOnClass(MethodMetadata data, Class<?> targetType) {
Expand Down
20 changes: 16 additions & 4 deletions core/src/main/java/feign/ReflectiveFeign.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public Map<String, MethodHandler> apply(Target target) {
if (!md.formParams().isEmpty() && md.template().bodyTemplate() == null) {
buildTemplate =
new BuildFormEncodedTemplateFromArgs(md, encoder, queryMapEncoder, target);
} else if (md.bodyIndex() != null) {
} else if (md.bodyIndex() != null || UnconditionalEncoder.class.isAssignableFrom(encoder.getClass())) {
buildTemplate = new BuildEncodedTemplateFromArgs(md, encoder, queryMapEncoder, target);
} else {
buildTemplate = new BuildTemplateByResolvingArgs(md, queryMapEncoder, target);
Expand Down Expand Up @@ -379,10 +379,22 @@ private BuildEncodedTemplateFromArgs(MethodMetadata metadata, Encoder encoder,
protected RequestTemplate resolve(Object[] argv,
RequestTemplate mutable,
Map<String, Object> variables) {
Object body = argv[metadata.bodyIndex()];
checkArgument(body != null, "Body parameter %s was null", metadata.bodyIndex());

boolean unconditionalEncoder = UnconditionalEncoder.class.isAssignableFrom(encoder.getClass());

Object body = null;
if (!unconditionalEncoder) {
body = argv[metadata.bodyIndex()];

This comment has been minimized.

Copy link
@fabiocarvalho777

fabiocarvalho777 Jul 7, 2021

Author Owner

This line has to be inside of this if to avoid a NPE.

checkArgument(body != null, "Body parameter %s was null", metadata.bodyIndex());

This comment has been minimized.

Copy link
@fabiocarvalho777

fabiocarvalho777 Jul 7, 2021

Author Owner

This line has to be outside the try/catch block otherwise caller won't have a chance to catch the IAE.

}

try {
encoder.encode(body, metadata.bodyType(), mutable);
if (unconditionalEncoder) {
UnconditionalEncoder unEncoder = (UnconditionalEncoder) encoder;
unEncoder.encode(argv, mutable);

This comment has been minimized.

Copy link
@fabiocarvalho777

fabiocarvalho777 Jul 7, 2021

Author Owner

Notice here I am passing argv as well

} else {
encoder.encode(body, metadata.bodyType(), mutable);
}
} catch (EncodeException e) {
throw e;
} catch (RuntimeException e) {
Expand Down
55 changes: 55 additions & 0 deletions core/src/main/java/feign/codec/UnconditionalEncoder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Copyright 2012-2020 The Feign Authors
*
* 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.
*/
package feign.codec;

import feign.RequestTemplate;
import java.lang.reflect.Type;

/**
* {@link Encoder} extension that allows user provided custom encoders to define the request message
* payload using only the request template and the method parameters, not requiring a specific and
* unique body object.
*
* This type of encoder is useful when an application needs a Feign client whose request payload is
* defined entirely by a custom Feign encoder regardless of how many parameters are declared at the
* client method. In this case, even with no presence of body parameter the encoder will have to
* know how to define the request payload (for example, based on the method name, method return
* type, and other metadata provided by custom annotations, all available via the provided
* {@link RequestTemplate} object).
*
* @author fabiocarvalho777@gmail.com
*/
public interface UnconditionalEncoder extends Encoder {

/**
* {@inheritDoc}
*/
@Override
default void encode(Object object, Type bodyType, RequestTemplate template)
throws EncodeException {
throw new UnsupportedOperationException(
"This encode method is not supported in this type of encoder, instead, use the overloaded version with parameters array and request template");
}

/**
* Produces message body exclusively based on the request template.
*
* @param parameters the values of the parameters passed by the client when calling the method,
* ordered according to parameters definition order.
* @param template the request template to populate.
* @throws EncodeException when encoding failed due to a checked exception.
*/
void encode(Object[] parameters, RequestTemplate template) throws EncodeException;

This comment has been minimized.

Copy link
@fabiocarvalho777

fabiocarvalho777 Jul 7, 2021

Author Owner

Notice the Object[] parameter here.


}

0 comments on commit 7067d23

Please sign in to comment.