{"id":78122,"date":"2018-06-18T16:00:22","date_gmt":"2018-06-18T13:00:22","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=78122"},"modified":"2018-06-18T12:07:36","modified_gmt":"2018-06-18T09:07:36","slug":"provide-client-libraries-apis","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html","title":{"rendered":"In the shoes of the consumer: do you really need to provide the client libraries for your APIs?"},"content":{"rendered":"<p>The beauty of the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">RESTful<\/a> web services and APIs is that any consumer which speaks <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">HTTP<\/a> protocol will be able to understand and use it. Nonetheless, the same dilemma pops up over and over again: should you accompany your web APis with the client libraries or not? If yes, what languages or\/and frameworks should you support?<\/p>\n<p>Quite often this is not really an easy question to answer. So let us take a step back and think about the overall idea for a moment: what are the values which client libraries may bring to the consumers?<\/p>\n<p>Someone may say to lower the barrier for adoption. Indeed, specifically in the case of strongly typed languages, exploring the API contracts from your favorite IDE (syntax highlighting and auto-completion please!) is quite handy. But by and large, the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">RESTful<\/a> web APIs are simple enough to start with and good documentation would be certainly more valuable here.<\/p>\n<p>Others may say it is good to shield the consumers from dealing with multiple API versions or rough edges. Also kind of make sense but I would argue it just hides the flaws with the way the web APIs in question are designed and evolve over time.<\/p>\n<p>All in all, no matter how many clients you decide to bundle, the APIs are still going to be accessible by any generic <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">HTTP<\/a> consumer (<a href=\"https:\/\/curl.haxx.se\/\">curl<\/a>, <a href=\"http:\/\/hc.apache.org\/httpcomponents-client-4.5.x\/index.html\">HttpClient<\/a>, <a href=\"https:\/\/docs.spring.io\/spring-framework\/docs\/current\/javadoc-api\/org\/springframework\/web\/client\/RestTemplate.html\">RestTemplate<\/a>, you name it). Giving a choice is great but the price to pay for maintenance could be really high. Could we do it better? And as you may guess already, we certainly have quite a few options hence this post.<\/p>\n<p>The key ingredient of the success here is to maintain an accurate specification of your <a href=\"https:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">RESTful<\/a> web APIs, using <a href=\"https:\/\/www.javacodegeeks.com\/2018\/05\/moving-with-the-times-towards-openapi-v3-0-0-adoption-in-jax-rs-apis.html\">OpenAPI v3.0<\/a> or even its predecessor, <a href=\"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html\">Swagger\/OpenAPI 2.0<\/a> (or <a href=\"https:\/\/raml.org\/\">RAML<\/a>, <a href=\"https:\/\/apiblueprint.org\/\">API Blueprint<\/a>, does not really matter much). In case of <a href=\"https:\/\/github.com\/OAI\/OpenAPI-Specification\">OpenAPI\/Swagger<\/a>, the tooling is the king: one could use <a href=\"https:\/\/github.com\/swagger-api\/swagger-codegen\">Swagger Codegen<\/a>, a template-driven engine, to generate API clients (and even server stubs) in many different languages, and this is what we are going to talk about in this post.<\/p>\n<p>To simplify the things, we are going to implement the consumer of the people management web API which we have built in the <a href=\"https:\/\/www.javacodegeeks.com\/2018\/05\/moving-with-the-times-towards-openapi-v3-0-0-adoption-in-jax-rs-apis.html\">previous post<\/a>. To begin with, we need to get its <a href=\"https:\/\/github.com\/OAI\/OpenAPI-Specification\/blob\/master\/versions\/3.0.0.md\">OpenAPI v3.0<\/a> specification in the <a href=\"https:\/\/en.wikipedia.org\/wiki\/YAML\">YAML<\/a> (or <a href=\"https:\/\/en.wikipedia.org\/wiki\/JSON\">JSON<\/a>) format.<\/p>\n<pre class=\"brush:java\">java -jar server-openapi\/target\/server-openapi-0.0.1-SNAPSHOT.jar<\/pre>\n<p>And then:<\/p>\n<pre class=\"brush:java\">wget http:\/\/localhost:8080\/api\/openapi.yaml<\/pre>\n<p>Awesome, the half of the job is done, literally. Now, let us allow <a href=\"https:\/\/github.com\/swagger-api\/swagger-codegen\">Swagger Codegen<\/a> to take a lead. In order to not complicate the matter, let&#8217;s assume that consumer is also Java application, so we could understand the mechanics without any difficulties (but Java is only one of the options, the <a href=\"https:\/\/github.com\/swagger-api\/swagger-codegen\">list of supported languages and frameworks<\/a> is astonishing).<\/p>\n<p>Along this post we are going to use <a href=\"https:\/\/github.com\/OpenFeign\/feign\">OpenFeign<\/a>, one of the most advanced Java <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">HTTP<\/a> client binders. Not only it is exceptionally simple to use, it offers quite a few integrations we are going to benefit from soon.<\/p>\n<pre class=\"brush:xml\">&lt;dependency&gt;\r\n    &lt;groupId&gt;io.github.openfeign&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;feign-core&lt;\/artifactId&gt;\r\n    &lt;version&gt;9.7.0&lt;\/version&gt;\r\n&lt;\/dependency&gt;\r\n\r\n&lt;dependency&gt;\r\n    &lt;groupId&gt;io.github.openfeign&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;feign-jackson&lt;\/artifactId&gt;\r\n    &lt;version&gt;9.7.0&lt;\/version&gt;\r\n&lt;\/dependency&gt;<\/pre>\n<p>The <a href=\"https:\/\/github.com\/swagger-api\/swagger-codegen\">Swagger Codegen<\/a> could be run as stand-alone application from command-line, or <a href=\"https:\/\/maven.apache.org\/\">Apache Maven<\/a> plugin (the latter is what we are going to use).<\/p>\n<pre class=\" brush:xml\">&lt;plugin&gt;\r\n    &lt;groupId&gt;io.swagger&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;swagger-codegen-maven-plugin&lt;\/artifactId&gt;\r\n    &lt;version&gt;3.0.0-rc1&lt;\/version&gt;\r\n    &lt;executions&gt;\r\n        &lt;execution&gt;\r\n            &lt;goals&gt;\r\n                &lt;goal&gt;generate&lt;\/goal&gt;\r\n            &lt;\/goals&gt;\r\n            &lt;configuration&gt;\r\n                &lt;inputSpec&gt;\/contract\/openapi.yaml&lt;\/inputSpec&gt;\r\n                &lt;apiPackage&gt;com.example.people.api&lt;\/apiPackage&gt;\r\n                &lt;language&gt;java&lt;\/language&gt;\r\n                &lt;library&gt;feign&lt;\/library&gt;\r\n                &lt;modelPackage&gt;com.example.people.model&lt;\/modelPackage&gt;\r\n                &lt;generateApiDocumentation&gt;false&lt;\/generateApiDocumentation&gt;\r\n                &lt;generateSupportingFiles&gt;false&lt;\/generateSupportingFiles&gt;\r\n                &lt;generateApiTests&gt;false&lt;\/generateApiTests&gt;\r\n                &lt;generateApiDocs&gt;false&lt;\/generateApiDocs&gt;\r\n                &lt;addCompileSourceRoot&gt;true&lt;\/addCompileSourceRoot&gt;\r\n                &lt;configOptions&gt;\r\n                    &lt;sourceFolder&gt;\/&lt;\/sourceFolder&gt;\r\n                    &lt;java8&gt;true&lt;\/java8&gt;\r\n                    &lt;dateLibrary&gt;java8&lt;\/dateLibrary&gt;\r\n                    &lt;useTags&gt;true&lt;\/useTags&gt;\r\n                &lt;\/configOptions&gt;\r\n            &lt;\/configuration&gt;\r\n        &lt;\/execution&gt;\r\n    &lt;\/executions&gt;\r\n&lt;\/plugin&gt;<\/pre>\n<p>If some of the options are not very clear, the <a href=\"https:\/\/github.com\/swagger-api\/swagger-codegen\">Swagger Codegen<\/a> has pretty good <a href=\"https:\/\/github.com\/swagger-api\/swagger-codegen\/tree\/master\/modules\/swagger-codegen-maven-plugin\">documentation<\/a> to look for clarifications. The important ones to pay attention to is <b>language<\/b> and <b>library<\/b>, which are set to <b>java<\/b> and <b>feign<\/b> respectively. The one thing to note though, the support of the <a href=\"https:\/\/github.com\/OAI\/OpenAPI-Specification\/blob\/master\/versions\/3.0.0.md\">OpenAPI v3.0<\/a> specification is mostly complete but you may encounter some issues nonetheless (as you noticed, the version is <b>3.0.0-rc1<\/b>).<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p>What you will get when your build finishes is the plain old Java interface, <b>PeopleApi<\/b>, annotated with <a href=\"https:\/\/github.com\/OpenFeign\/feign\">OpenFeign<\/a> annotations, which is direct projection of the people management web API specification (which comes from <b>\/contract\/openapi.yaml<\/b>). Please notice that all model classes are generated as well.<\/p>\n<pre class=\"brush:java\">@javax.annotation.Generated(\r\n    value = \"io.swagger.codegen.languages.java.JavaClientCodegen\",\r\n    date = \"2018-06-17T14:04:23.031Z[Etc\/UTC]\"\r\n)\r\npublic interface PeopleApi extends ApiClient.Api {\r\n    @RequestLine(\"POST \/api\/people\")\r\n    @Headers({\"Content-Type: application\/json\", \"Accept: application\/json\"})\r\n    Person addPerson(Person body);\r\n\r\n    @RequestLine(\"DELETE \/api\/people\/{email}\")\r\n    @Headers({\"Content-Type: application\/json\"})\r\n    void deletePerson(@Param(\"email\") String email);\r\n\r\n    @RequestLine(\"GET \/api\/people\/{email}\")\r\n    @Headers({\"Accept: application\/json\"})\r\n    Person findPerson(@Param(\"email\") String email);\r\n\r\n    @RequestLine(\"GET \/api\/people\")\r\n    @Headers({\"Accept: application\/json\"})\r\n    List&lt;Person&gt; getPeople();\r\n}<\/pre>\n<p>Let us compare it with <a href=\"https:\/\/github.com\/swagger-api\/swagger-ui\">Swagger UI<\/a> interpretation of the same specification, available at <a href=\"http:\/\/localhost:8080\/api\/api-docs?url=\/api\/openapi.json\">http:\/\/localhost:8080\/api\/api-docs?url=\/api\/openapi.json<\/a>:<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/06\/people-api-spec.png\"><img decoding=\"async\" class=\"aligncenter wp-image-78142\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/06\/people-api-spec.png\" alt=\"client libraries api spec\" width=\"860\" height=\"169\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/06\/people-api-spec.png 1600w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/06\/people-api-spec-300x59.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/06\/people-api-spec-768x151.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/06\/people-api-spec-1024x201.png 1024w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>It looks right at the first glance but we have better ensure things work out as expected. Once we have <a href=\"https:\/\/github.com\/OpenFeign\/feign\">OpenFeign<\/a>-annotated interface, it could be made functional (in this case, implemented through proxies) using the family of <b>Feign builders<\/b>, for example:<\/p>\n<pre class=\"brush:java\">final PeopleApi api = Feign\r\n    .builder()\r\n    .client(new OkHttpClient())\r\n    .encoder(new JacksonEncoder())\r\n    .decoder(new JacksonDecoder())\r\n    .logLevel(Logger.Level.HEADERS)\r\n    .options(new Request.Options(1000, 2000))\r\n    .target(PeopleApi.class, \"http:\/\/localhost:8080\/\");<\/pre>\n<p>Great, fluent builder style rocks. Assuming our people management web APIs server is up and running (by default, it is going to be available at <a href=\"http:\/\/localhost:8080\/\">http:\/\/localhost:8080\/<\/a>):<\/p>\n<pre class=\" brush:java\">java -jar server-openapi\/target\/server-openapi-0.0.1-SNAPSHOT.jar<\/pre>\n<p>We could communicate with it by calling freshly built <b>PeopleApi<\/b> instance methods, as in the code snippet below.:<\/p>\n<pre class=\" brush:java\">final Person person = api.addPerson(\r\n        new Person()\r\n            .email(\"a@b.com\")\r\n            .firstName(\"John\")\r\n            .lastName(\"Smith\"));<\/pre>\n<p>It is really cool, if we rewind it back a bit, we actually did nothing. Everything is given to us for free with only web API specification available! But let us not stop here and remind ourselves that using Java interfaces will not eliminate the reality that we are dealing with remote systems. And things are going to fail here, sooner or later, no doubts.<\/p>\n<p>Not so long ago we <a href=\"https:\/\/www.javacodegeeks.com\/2016\/06\/things-may-get-control-circuit-breakers-practice-hystrix.html\">have learned about circuit breakers<\/a> and how useful they are when properly applied in the context of distributed systems. It would be really awesome to somehow introduce this feature into our <a href=\"https:\/\/github.com\/OpenFeign\/feign\">OpenFeign<\/a>-based client. Please welcome another member of the family, <b>HystrixFeign builder<\/b>, the seamless integration with <a href=\"https:\/\/github.com\/Netflix\/Hystrix\">Hytrix<\/a> library:<\/p>\n<pre class=\"brush:java\">final PeopleApi api = HystrixFeign\r\n    .builder()\r\n    .client(new OkHttpClient())\r\n    .encoder(new JacksonEncoder())\r\n    .decoder(new JacksonDecoder())\r\n    .logLevel(Logger.Level.HEADERS)\r\n    .options(new Request.Options(1000, 2000))\r\n    .target(PeopleApi.class, \"http:\/\/localhost:8080\/\");<\/pre>\n<p>The only thing we need to do is just to add these two dependencies (strictly speaking <b>hystrix-core<\/b> is not really needed if you do not mind to stay on older version) to consumer&#8217;s <b>pom.xml<\/b> file.<\/p>\n<pre class=\"brush:xml\">&lt;dependency&gt;\r\n    &lt;groupId&gt;io.github.openfeign&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;feign-hystrix&lt;\/artifactId&gt;\r\n    &lt;version&gt;9.7.0&lt;\/version&gt;\r\n&lt;\/dependency&gt;\r\n\r\n&lt;dependency&gt;\r\n    &lt;groupId&gt;com.netflix.hystrix&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;hystrix-core&lt;\/artifactId&gt;\r\n    &lt;version&gt;1.5.12&lt;\/version&gt;\r\n&lt;\/dependency&gt;<\/pre>\n<p>Arguably, this is one of the best examples of how easy and straightforward integration could be. But even that is not the end of the story. Observability in the distributed systems is as important as never and as <a href=\"https:\/\/aredko.blogspot.com\/2014\/02\/knowing-how-all-your-components-work.html\">we have learned a while ago<\/a>, distributed tracing is tremendously useful in helping us out here. And again, <a href=\"https:\/\/github.com\/OpenFeign\/feign\">OpenFeign<\/a> has support for it right out of the box, let us take a look.<\/p>\n<p><a href=\"https:\/\/github.com\/OpenFeign\/feign\">OpenFeign<\/a> fully integrates with <a href=\"http:\/\/opentracing.io\/\">OpenTracing<\/a>-compatible tracer. The <a href=\"https:\/\/github.com\/jaegertracing\/jaeger\">Jaeger<\/a> tracer is one of those, which among other things has really nice web UI front-end to explore traces and dependencies. Let us run it first, luckily it is fully <a href=\"https:\/\/www.docker.com\/\">Docker<\/a>-ized.<\/p>\n<pre class=\"brush:bash\">docker run -d -e \\\r\n    COLLECTOR_ZIPKIN_HTTP_PORT=9411 \\\r\n    -p 5775:5775\/udp \\\r\n    -p 6831:6831\/udp \\\r\n    -p 6832:6832\/udp \\\r\n    -p 5778:5778 \\\r\n    -p 16686:16686 \\\r\n    -p 14268:14268 \\\r\n    -p 9411:9411 \\\r\n    jaegertracing\/all-in-one:latest<\/pre>\n<p>A couple of additional dependencies have to be introduced in order to <a href=\"https:\/\/github.com\/OpenFeign\/feign\">OpenFeign<\/a> client to be aware of the <a href=\"http:\/\/opentracing.io\/\">OpenTracing<\/a> capabilities.<\/p>\n<pre class=\"brush:xml\">&lt;dependency&gt;\r\n    &lt;groupId&gt;io.github.openfeign.opentracing&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;feign-opentracing&lt;\/artifactId&gt;\r\n    &lt;version&gt;0.1.0&lt;\/version&gt;\r\n&lt;\/dependency&gt;\r\n\r\n&lt;dependency&gt;\r\n    &lt;groupId&gt;io.jaegertracing&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;jaeger-core&lt;\/artifactId&gt;\r\n    &lt;version&gt;0.29.0&lt;\/version&gt;\r\n&lt;\/dependency&gt;<\/pre>\n<p>From the <b>Feign<\/b> builder side, the only change (besides the introduction of the tracer instance) is to wrap up the client into <b>TracingClient<\/b>, like the snippet below demonstrates:<\/p>\n<pre class=\"brush:java\">final Tracer tracer = new Configuration(\"consumer-openapi\")\r\n    .withSampler(\r\n        new SamplerConfiguration()\r\n            .withType(ConstSampler.TYPE)\r\n            .withParam(new Float(1.0f)))\r\n    .withReporter(\r\n        new ReporterConfiguration()\r\n            .withSender(\r\n                new SenderConfiguration()\r\n                    .withEndpoint(\"http:\/\/localhost:14268\/api\/traces\")))\r\n    .getTracer();\r\n            \r\nfinal PeopleApi api = Feign\r\n    .builder()\r\n    .client(new TracingClient(new OkHttpClient(), tracer))\r\n    .encoder(new JacksonEncoder())\r\n    .decoder(new JacksonDecoder())\r\n    .logLevel(Logger.Level.HEADERS)\r\n    .options(new Request.Options(1000, 2000))\r\n    .target(PeopleApi.class, \"http:\/\/localhost:8080\/\");<\/pre>\n<p>On the server-side we also need to integrate with <a href=\"http:\/\/opentracing.io\/\">OpenTracing<\/a> as well. The <a href=\"http:\/\/cxf.apache.org\/\">Apache CXF<\/a> has <a href=\"http:\/\/cxf.apache.org\/docs\/using-opentracing.html\">first-class support for it<\/a>, bundled into <b>cxf-integration-tracing-opentracing<\/b> module. Let us include it as the dependency, this time to server&#8217;s <b>pom.xml<\/b>.<\/p>\n<pre class=\"brush:xml\">&lt;dependency&gt;\r\n    &lt;groupId&gt;org.apache.cxf&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;cxf-integration-tracing-opentracing&lt;\/artifactId&gt;\r\n    &lt;version&gt;3.2.4&lt;\/version&gt;\r\n&lt;\/dependency&gt;<\/pre>\n<p>Depending on the way your configure your applications, there should be an instance of the tracer available which should be passed later on to the <b>OpenTracingFeature<\/b>, for example.<\/p>\n<pre class=\"brush:java\">\/\/ Create tracer\r\nfinal Tracer tracer = new Configuration(\r\n        \"server-openapi\", \r\n        new SamplerConfiguration(ConstSampler.TYPE, 1),\r\n        new ReporterConfiguration(new HttpSender(\"http:\/\/localhost:14268\/api\/traces\"))\r\n    ).getTracer();\r\n\r\n\/\/ Include OpenTracingFeature feature\r\nfinal JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();\r\nfactory.setProvider(new OpenTracingFeature(tracer()));\r\n...\r\nfactory.create()<\/pre>\n<p>From now on, the invocation of the any people management API endpoint through generated <a href=\"https:\/\/github.com\/OpenFeign\/feign\">OpenFeign<\/a> client will be fully traceable in the <a href=\"https:\/\/github.com\/jaegertracing\/jaeger\">Jaeger<\/a> web UI, available at <a href=\"http:\/\/localhost:16686\/search\">http:\/\/localhost:16686\/search<\/a> (assuming your <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> host is <b>localhost<\/b>).<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/06\/jaeger.png\"><img decoding=\"async\" class=\"aligncenter wp-image-78141\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/06\/jaeger.png\" alt=\"client libraries consumer openapi\" width=\"860\" height=\"333\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/06\/jaeger.png 1600w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/06\/jaeger-300x116.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/06\/jaeger-768x298.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/06\/jaeger-1024x397.png 1024w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>Our scenario is pretty simple but imagine the real applications where dozen of external service calls could happen while the single request travels through the system. Without distributed tracing in place, every issue has a chance to turn into a mystery.<\/p>\n<p>As a side note, if you look closer to the trace from the picture, you may notice that server and consumer use different versions of the <a href=\"https:\/\/github.com\/jaegertracing\/jaeger\">Jaeger<\/a> API. This is not a mistake since the latest released version of <a href=\"http:\/\/cxf.apache.org\/docs\/using-opentracing.html\">Apache CXF<\/a> is using older <a href=\"http:\/\/opentracing.io\/\">OpenTracing<\/a> API version (and as such, older <a href=\"https:\/\/github.com\/jaegertracing\/jaeger\">Jaeger<\/a> client API) but it does not prevent things to work as expected.<\/p>\n<p>With that, it is time to wrap up. Hopefully, the benefits of contract-based (or even better, contract-first) development in the world of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">RESTful<\/a> web services and APIs become more and more apparent: generation of the smart clients, <a href=\"https:\/\/www.javacodegeeks.com\/2016\/11\/keep-promises-contract-based-testing-jax-rs-apis.html\">consumer-driven contract test<\/a>, discoverability and rich documentation are just a few to mention. Please make use of it!<\/p>\n<p>The complete project sources are available on <a href=\"https:\/\/github.com\/reta\/openapi-contract-client-generation\">Github<\/a>.<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td>Published on Java Code Geeks with permission by Andrey Redko, partner at our <a href=\"\/\/www.javacodegeeks.com\/join-us\/jcg\/\" target=\"_blank\" rel=\"noopener\">JCG program<\/a>. See the original article here: <a href=\"http:\/\/aredko.blogspot.com\/2018\/06\/in-shoes-of-consumer-do-you-really-need.html\" target=\"_blank\" rel=\"noopener\">In the shoes of the consumer: do you really need to provide the client libraries for your APIs?<\/a><\/p>\n<p>Opinions expressed by Java Code Geeks contributors are their own.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>The beauty of the RESTful web services and APIs is that any consumer which speaks HTTP protocol will be able to understand and use it. Nonetheless, the same dilemma pops up over and over again: should you accompany your web APis with the client libraries or not? If yes, what languages or\/and frameworks should you &hellip;<\/p>\n","protected":false},"author":141,"featured_media":112,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[1769,1002,1770,1768,1029],"class_list":["post-78122","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-http","tag-hystrix","tag-jaeger","tag-restful","tag-swagger"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>In the shoes of the consumer: do you really need to provide the client libraries for your APIs? - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Interested to learn if you should provide client libraries with your web APis or not? Then check out our article where we try to answer this dilemma.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"In the shoes of the consumer: do you really need to provide the client libraries for your APIs? - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Interested to learn if you should provide client libraries with your web APis or not? Then check out our article where we try to answer this dilemma.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2018-06-18T13:00:22+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Andrey Redko\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andrey Redko\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/06\\\/provide-client-libraries-apis.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/06\\\/provide-client-libraries-apis.html\"},\"author\":{\"name\":\"Andrey Redko\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/771a6504862edc45322776832cbce413\"},\"headline\":\"In the shoes of the consumer: do you really need to provide the client libraries for your APIs?\",\"datePublished\":\"2018-06-18T13:00:22+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/06\\\/provide-client-libraries-apis.html\"},\"wordCount\":1387,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/06\\\/provide-client-libraries-apis.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/enterprise-java-logo.jpg\",\"keywords\":[\"http\",\"Hystrix\",\"jaeger\",\"RESTful\",\"Swagger\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/06\\\/provide-client-libraries-apis.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/06\\\/provide-client-libraries-apis.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/06\\\/provide-client-libraries-apis.html\",\"name\":\"In the shoes of the consumer: do you really need to provide the client libraries for your APIs? - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/06\\\/provide-client-libraries-apis.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/06\\\/provide-client-libraries-apis.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/enterprise-java-logo.jpg\",\"datePublished\":\"2018-06-18T13:00:22+00:00\",\"description\":\"Interested to learn if you should provide client libraries with your web APis or not? Then check out our article where we try to answer this dilemma.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/06\\\/provide-client-libraries-apis.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/06\\\/provide-client-libraries-apis.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/06\\\/provide-client-libraries-apis.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/enterprise-java-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/enterprise-java-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"java-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/06\\\/provide-client-libraries-apis.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"In the shoes of the consumer: do you really need to provide the client libraries for your APIs?\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/771a6504862edc45322776832cbce413\",\"name\":\"Andrey Redko\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"caption\":\"Andrey Redko\"},\"description\":\"Andriy is a well-grounded software developer with more then 12 years of practical experience using Java\\\/EE, C#\\\/.NET, C++, Groovy, Ruby, functional programming (Scala), databases (MySQL, PostgreSQL, Oracle) and NoSQL solutions (MongoDB, Redis).\",\"sameAs\":[\"http:\\\/\\\/aredko.blogspot.com\\\/\",\"http:\\\/\\\/ca.linkedin.com\\\/in\\\/aredko\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/andrey-redko\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"In the shoes of the consumer: do you really need to provide the client libraries for your APIs? - Java Code Geeks","description":"Interested to learn if you should provide client libraries with your web APis or not? Then check out our article where we try to answer this dilemma.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html","og_locale":"en_US","og_type":"article","og_title":"In the shoes of the consumer: do you really need to provide the client libraries for your APIs? - Java Code Geeks","og_description":"Interested to learn if you should provide client libraries with your web APis or not? Then check out our article where we try to answer this dilemma.","og_url":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2018-06-18T13:00:22+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","type":"image\/jpeg"}],"author":"Andrey Redko","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Andrey Redko","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html"},"author":{"name":"Andrey Redko","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/771a6504862edc45322776832cbce413"},"headline":"In the shoes of the consumer: do you really need to provide the client libraries for your APIs?","datePublished":"2018-06-18T13:00:22+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html"},"wordCount":1387,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","keywords":["http","Hystrix","jaeger","RESTful","Swagger"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html","url":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html","name":"In the shoes of the consumer: do you really need to provide the client libraries for your APIs? - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","datePublished":"2018-06-18T13:00:22+00:00","description":"Interested to learn if you should provide client libraries with your web APis or not? Then check out our article where we try to answer this dilemma.","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","width":150,"height":150,"caption":"java-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2018\/06\/provide-client-libraries-apis.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"In the shoes of the consumer: do you really need to provide the client libraries for your APIs?"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/771a6504862edc45322776832cbce413","name":"Andrey Redko","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","caption":"Andrey Redko"},"description":"Andriy is a well-grounded software developer with more then 12 years of practical experience using Java\/EE, C#\/.NET, C++, Groovy, Ruby, functional programming (Scala), databases (MySQL, PostgreSQL, Oracle) and NoSQL solutions (MongoDB, Redis).","sameAs":["http:\/\/aredko.blogspot.com\/","http:\/\/ca.linkedin.com\/in\/aredko"],"url":"https:\/\/www.javacodegeeks.com\/author\/andrey-redko"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/78122","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/141"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=78122"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/78122\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/112"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=78122"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=78122"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=78122"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}