2

With spring boot 2.6.0 (or above) is it possible to generate a rest client from a a controller interface?

Im wondering if its possible to build spring application like this following use case.

Spring application A needs to call spring application B rest interface

Spring application B is a multimodule project that produces server jar, and a api jar

Spring application A imports the B's API jar

Spring application A uses controller interface from B Api jar to make a rest client based on spring annotations.

B Api jar:


   @RestsController
   public interface MyApplicationAPI {

        @GetMapping("/api/some-endpoint)
        public SomeDto someEndpoint(SomeDTO obj);

   }

B server jar:

   public class BApplicationAPIImpl implements MyApplicationAPI {

        
        public SomeDto someEndpoint(SomeDTO obj) {
            return xxx;

And finally within A application:

      MyApplicationAPI restClient = Some.magic(MyApplicationAPI.class, "http://bappurl.com")
      SomeDto response = restClient.someEndpoint(param);

I believe that framework RestEasy supports similar approach, but you have to rely on JAXRS annotations.

Is there anything like that for spring framework? Or even better is there anything like this within spring already - i would prefer to rely on spring inhouse libraries and tools, rather than importing entire resteasy and jaxrs.

2
  • I'm not aware of something like this. IMHO even it sounds tempting, I won't use it: It is adding a strong dependency to a (Java) implementation to consume the service. Maybe in the future this B service moves to another technology and developed new features. Then you have to implement a client (RestEasy, WebClient, any) anyway. For me, REST, web services, etc is a lot of create the most possible independent artifacts. Commented Sep 17, 2022 at 17:53
  • @PeterMmm that doesn't really mean server and client are both bind to Spring. Client can keep using MyApplicationAPI interface as a API contract and server would use other framework. The good thing about this idea is that both server and client use the same contract, just like gRPC, so you can enforce it (to some extend) at compile time. Commented Jan 4, 2023 at 12:19

1 Answer 1

3

Spring Framework 6 (and Spring Boot 3) will have declarative HTTP interfaces (see documentation). However, they won't use the same annotations as controllers, but separate ones. So your example where you use the same interface for both controller and client won't be possible.

Code snippet from the documentation:

interface RepositoryService {

    @GetExchange("/repos/{owner}/{repo}")
    Repository getRepository(@PathVariable String owner, @PathVariable String repo);

    // more HTTP exchange methods...

}

Initialization (the Some.magic() part in your question) can be done with WebClient. As can be seen in the same documentation:

WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
HttpServiceProxyFactory factory = WebClientAdapter.createHttpServiceProxyFactory(client);
factory.afterPropertiesSet();

RepositoryService service = factory.createClient(RepositoryService.class);
Sign up to request clarification or add additional context in comments.

2 Comments

Would it make sense to have '@GetMapping' and '@GetExchange' on the same interface method?
You actually can use the Exchange-Annotations in a Controller and don't use the Mapping-Annotations at all if you don't need its additional features. See: docs.spring.io/spring-framework/reference/web/webmvc/… (at the bottom of the page)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.