Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalized target-type Inference #445

Open
rjbgaspar opened this issue Mar 19, 2022 · 1 comment
Open

Generalized target-type Inference #445

rjbgaspar opened this issue Mar 19, 2022 · 1 comment

Comments

@rjbgaspar
Copy link

Hi,

I do not understand why we cannot set the returned target type on a method…

This is my feign reactive interface for accessing the Fargo API

package com.gv.zeppelin.service.fargo;

import com.gv.zeppelin.service.dto.fargo.ACL247StarterProcessDTO;
import feign.Headers;
import feign.Param;
import feign.QueryMap;
import feign.RequestLine;
import org.springframework.util.MultiValueMap;
import reactor.core.publisher.Mono;

@Headers({"Accept: application/json"})
public interface FargoApi {
    @RequestLine("GET /api/v1/query/{slug}")
    <T> Mono<T> queryForList(@Param("slug") String slug,
                             @QueryMap MultiValueMap<String, Object> queryMap,
                             Class<T> elementClass);

    @RequestLine("GET /api/v1/query/{slug}")
    Mono<ACL247StarterProcessDTO> queryForList(@Param("slug") String slug,
                                               @QueryMap MultiValueMap<String, Object> queryMap);
}

This is my test class

package com.gv.zeppelin.service.fargo;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.gv.zeppelin.service.dto.XConverterRequestDTO;
import com.gv.zeppelin.service.dto.fargo.ACL247StarterProcessDTO;
import com.gv.zeppelin.service.fargo.query.Query;
import com.gv.zeppelin.service.fargo.query.QuerySlug;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ClientCodecConfigurer;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;
import reactivefeign.webclient.WebReactiveFeign;
import reactor.test.StepVerifier;

import java.util.List;


class FargoApiTest {
    private static ObjectMapper baseConfig = new ObjectMapper();
    private static FargoApi fargoApi;
    private static XConverterRequestDTO xConverterRequestDTO = new XConverterRequestDTO();

    @BeforeAll
    public static void beforeAll() {
        var builder = fargoWebClient(baseConfig);

        fargoApi = WebReactiveFeign
            .<FargoApi>builder(builder)
            .target(FargoApi.class, "http://172.16.9.5:50010");

        xConverterRequestDTO.setWorkOrders(List.of("ZPH-V121-00122"));
        xConverterRequestDTO.setWorkOrders(List.of("MFG-V121-008485", "MFG-V121-008486"));
    }

    private static WebClient.Builder fargoWebClient(ObjectMapper baseConfig) {
        return WebClient.builder()
            .exchangeStrategies(ExchangeStrategies.builder()
                .codecs(FargoApiTest::configureClientCodecs)
                .build()
            );
    }

    private static void configureClientCodecs(ClientCodecConfigurer configurer) {
        configurer
            .defaultCodecs()
            .maxInMemorySize(16 * 1024 * 1024);

        configurer
            .defaultCodecs()
            .jackson2JsonEncoder(
                new Jackson2JsonEncoder(baseConfig, MediaType.APPLICATION_JSON));
        configurer
            .defaultCodecs()
            .jackson2JsonDecoder(
                new Jackson2JsonDecoder(baseConfig, MediaType.APPLICATION_JSON));
    }

    /**
     * Works
     */
    @Test
    public void queryForList() {
        var mono  = fargoApi.queryForList(
            QuerySlug.ERP_SAGE_X3_ACL_247_STARTER_PROCESSOR.value(),
            Query.toQueryMap(xConverterRequestDTO)
        );

        StepVerifier.create(mono)
            .expectNextMatches(response -> response.getData().size() == 1)
            .verifyComplete();
    }

    /**
     * Do not works
     */
    @Test
    public void queryForListWithGeneralizedTargetType() {
        var mono  = fargoApi.queryForList(
            QuerySlug.ERP_SAGE_X3_ACL_247_STARTER_PROCESSOR.value(),
            Query.toQueryMap(xConverterRequestDTO),
            ACL247StarterProcessDTO.class
        );

        StepVerifier.create(mono)
            .expectNextMatches(response -> response.getData().size() == 1)
            .verifyComplete();
    }
}

This is the stack trace ouput by the queryForListWithGeneralizedTargetType test

2022-03-19 15:14:32.099 DEBUG   --- [           main] r.client.log.DefaultReactiveLogger       : [FargoApi#queryForList(String,MultiValueMap,Class)]--->GET http://172.16.9.5:50010/api/v1/query/erp-sage-x3-acl-247-starter-processor?manufacturingPlan=&workOrder=MFG-V121-008485&workOrder=MFG-V121-008486&tag= HTTP/1.1
2022-03-19 15:14:33.333 DEBUG   --- [actor-tcp-nio-2] r.client.log.DefaultReactiveLogger       : [FargoApi#queryForList(String,MultiValueMap,Class)]<--- headers takes 1234 milliseconds

java.lang.AssertionError: expectation failed (failed running expectation on signal [onNext({data=[{order_number=ENC-V121/00929, order_line=6000, order_sequence=6000, manufacturing_plan=ZPH-V121-00122, kit_number=KIT-V121-02113, work_order=MFG-V121-008486, planned_quantity=1.0, product=0021237, description=Porta I19V1G Favo Mdf 28 + Ptx 3 OF Faia Vap 2000.0x400.0x35.0, exterior_color=FV, interior_color=FV, opening_side=ESQR, access=IN, access_val_1=IN, access_val_2=push, ariporta_type=AB01A.LM.2, product_family_code=PI0, product_family_description=, length=2000.0, width=400.0, thickness=35.0, expected_lot=ZLT-0000001921, glass_open_type=G, hinge_quantity=3, lock_height=0, edge_shape_t=1, edge_shape_description_t=0° S/boleado (lacagem), edge_shape_r=2, edge_shape_description_r=0° C/boleado (standard), edge_shape_b=1, edge_shape_description_b=0° S/boleado (lacagem), edge_shape_l=2, edge_shape_description_l=0° C/boleado (standard), edge_shape_mechanization_t={"rebated_width":0,"rebated_depth":0}, edge_shape_mechanization_r={"rebated_width":0,"rebated_depth":0}, edge_shape_mechanization_b={"rebated_width":0,"rebated_depth":0}, edge_shape_mechanization_l={"rebated_width":0,"rebated_depth":0}, hinges=[{"type":"hinge","item":"0009195","description":"400 Rev.Esq NI","model":"Q37","macro_name":"zConcealedHinge1","macro_value":"\/\/ 400\ndouble hingePositionY = openingSide.ToUpper().StartsWith(\"ESQ\") ? DZ - (7.5 + 20 \/ 2) : (7.5 + 20 \/ 2);\ndouble hingeAngle = 0;\ndouble hingeLength1 = 100;\ndouble hingeWidth = 20;\ndouble hingeRadius = 10;\ndouble hingeDepth1 = 2.6;\ndouble hingeInputFeed = 0;\ndouble hingeFeed = 0;\ndouble hingeRotation = 0;\nint hingeHood = 0;\nstring hingeTool = \"031\";\nstring hingeHead = \"1\";\nstring hingeFace = \"Back\";"}]}]})] with [java.lang.ClassCastException]:
class java.util.LinkedHashMap cannot be cast to class com.gv.zeppelin.service.dto.fargo.ACL247StarterProcessDTO (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.gv.zeppelin.service.dto.fargo.ACL247StarterProcessDTO is in unnamed module of loader 'app'))

	at reactor.test.DefaultStepVerifierBuilder.failPrefix(DefaultStepVerifierBuilder.java:2171)
	at reactor.test.DefaultStepVerifierBuilder.fail(DefaultStepVerifierBuilder.java:2167)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onExpectation(DefaultStepVerifierBuilder.java:1252)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onNext(DefaultStepVerifierBuilder.java:905)
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816)
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249)
	at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539)
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:151)
	at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:295)
	at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337)
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816)
	at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:159)
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142)
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260)
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142)
	at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:400)
	at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:419)
	at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:473)
	at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:702)
	at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:93)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:327)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:299)
	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:833)
	Suppressed: java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class com.gv.zeppelin.service.dto.fargo.ACL247StarterProcessDTO (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.gv.zeppelin.service.dto.fargo.ACL247StarterProcessDTO is in unnamed module of loader 'app')
		at reactor.test.DefaultStepVerifierBuilder.lambda$expectNextMatches$10(DefaultStepVerifierBuilder.java:430)
		at reactor.test.DefaultStepVerifierBuilder$SignalEvent.test(DefaultStepVerifierBuilder.java:1909)
		at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onSignal(DefaultStepVerifierBuilder.java:1270)
		at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onExpectation(DefaultStepVerifierBuilder.java:1215)
		... 46 more

Is it possible to make it work?

Thanks in advance.

@kptfh
Copy link
Collaborator

kptfh commented Mar 29, 2022

We support only features that are present in OpenFeign.
I doubt if OpenFeign have this feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants