Hi,

I'm having the following 2 FeignClient configurations

@Configuration
public class ServiceAClientConfiguration {

    @FeignClient(name = "serviceA", url = "${service.a.url}", configuration = ServiceAClientFeignConfiguration.class)
    public interface ServiceAClient extends ServiceAResource {
    }

    @Configuration
    public static class ServiceAClientFeignConfiguration {

        @Bean
        public Decoder feignDecoder(@Qualifier("_halObjectMapper") ObjectMapper objectMapper) {
            ObjectMapper kebabObjectMapper = objectMapper.copy().setPropertyNamingStrategy(KEBAB_CASE);
            HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(kebabObjectMapper);
            ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
            return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
        }
    }
}
@Configuration
public class ServiceBClientConfiguration {

    @FeignClient(name = "serviceB", url = "${service.b.url}", configuration = ServiceBClientFeignConfiguration.class)
    public interface ServiceBClient extends ServiceBResource {
    }

    @Configuration
    public static class ServiceBClientFeignConfiguration {

        @Bean
        public Decoder feignDecoder(@Qualifier("_halObjectMapper") ObjectMapper objectMapper) {
            ObjectMapper snakeObjectMapper = objectMapper.copy().setPropertyNamingStrategy(SNAKE_CASE);
            HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(snakeObjectMapper);
            ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
            return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
        }
    }
}

Both of these services talk in a different JSON format. Service A is using KEBAB casing, service B is using SNAKE casing. By tweaking the object mapper, I was hoping to talk with the different services.

However, what I now see is that the FeignClient for service A is using the same converter as of service B, and so using the same object mapper of service B. It's unable to talk with a KEBAB casing service as the object mapper is expecting SNAKE casing.

I read this issue (#1211) which is kind of similar of what I'm facing, but I'm using different names for the FeignClients, so it should not be the root cause.

Is it possible my problem is actually the same as #1211? And the only solution is to create the feign clients manually?

Comment From: ryanjbaxter

Remove the @Configuration annotation from the configuration classes.
See the note in http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/single/spring-cloud.html#_logging_configuration

Comment From: jochenhebbrecht

Hi @ryanjbaxter ,

Thanks for your fast feedback! Are you talking about the @Configuration on the ServiceAClientConfiguration class or on the ServiceAClientFeignConfiguration class.

I also see your posting a link to logging configuration. I was wondering what the link is between my problem and the logging configuration?

Thnx! Jochen

Comment From: ryanjbaxter

Yes that is what I am talking about.

Sorry I posted the wrong link http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/single/spring-cloud.html#spring-cloud-feign-overriding-defaults

Comment From: jochenhebbrecht

Ok, this bring me in the following situation:

@Configuration
public class ServiceAClientConfiguration {

    @FeignClient(name = "serviceA", url = "${service.a.url}", configuration = ServiceAClientFeignConfiguration.class)
    public interface ServiceAClient extends ServiceAResource {
    }

    public static class ServiceAClientFeignConfiguration {

        @Bean
        public Decoder feignDecoder(@Qualifier("_halObjectMapper") ObjectMapper objectMapper) {
            ObjectMapper kebabObjectMapper = objectMapper.copy().setPropertyNamingStrategy(KEBAB_CASE);
            HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(kebabObjectMapper);
            ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
            return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
        }
    }
}
@Configuration
public class ServiceBClientConfiguration {

    @FeignClient(name = "serviceB", url = "${service.b.url}", configuration = ServiceBClientFeignConfiguration.class)
    public interface ServiceBClient extends ServiceBResource {
    }

    public static class ServiceBClientFeignConfiguration {

        @Bean
        public Decoder feignDecoder(@Qualifier("_halObjectMapper") ObjectMapper objectMapper) {
            ObjectMapper snakeObjectMapper = objectMapper.copy().setPropertyNamingStrategy(SNAKE_CASE);
            HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(snakeObjectMapper);
            ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
            return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
        }
    }
}

When booting the application, the custom feign configurations are still being loaded (I added a breakpoint to be sure they would still be loaded ) but I still see the converter of service B ending up in the configuration of service A :-( ...

Comment From: ryanjbaxter

Maybe also try removing the @Bean annotations?

Comment From: jochenhebbrecht

Already tried that as well - the configurations still get loaded, but the converters are still being mixed up

Comment From: ryanjbaxter

Please provide a sample that reproduces the problem.

Comment From: jochenhebbrecht

Yes, I understand that it's hard now to understand what exactly the problem is. I do appreciate your very fast feedback!

I was successful in isolating the problem by creating a small project which only initializes the feign clients and talks to existing services. But you would still not be able to run that application as you need my services. I guess that won't be enough for you? And you would like me to deliver 2 small REST services as well? 1 speaking KEBAB casing, 1 speaking SNAKE casing?

Comment From: ryanjbaxter

doesnt necessarily need to be using the KEBAB and SNAKE casing just something that demonstrates the configuration not be applied correctly to the services

Comment From: jochenhebbrecht

Ok, I'll see what I can do. I'll probably come back to you after the weekend. You can, for now, mark this issue as 'Waiting for feedback'

Comment From: jochenhebbrecht

Hi @ryanjbaxter,

I was able to create a small 'test' project which you could easily use to reproduce the problem. However, by creating those 'dummy' services, it seems like that I can't reproduce the problem anymore.

This actually proved to me that the feign client library works like it should work, and there's a big chance there's something wrong in my project which breaks the stability of the feign clients.

This is no longer an issue for spring-cloud-netflix, so I'm closing this issue. I do want to thank you for your feedback! The tip on the removal of the @Configuration was very valuable to me!

Jochen

Comment From: educostadev

Remove the @Configuration saved my day!

Comment From: paulkeogh

Not just configuration... any Spring annotation.

Comment From: arvinxian

Remove the @configuration also saved my day!