<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gravitee</title>
    <description>The latest articles on DEV Community by Gravitee (@gravitee).</description>
    <link>https://dev.to/gravitee</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F5642%2Fc3694532-9a97-4e5c-ab4f-051233f1fa6c.png</url>
      <title>DEV Community: Gravitee</title>
      <link>https://dev.to/gravitee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gravitee"/>
    <language>en</language>
    <item>
      <title>Write your own policy with Gravitee.io API Management 4.0.0</title>
      <dc:creator>Yann Tavernier</dc:creator>
      <pubDate>Thu, 28 Sep 2023 05:17:35 +0000</pubDate>
      <link>https://dev.to/gravitee/write-your-own-policy-with-graviteeio-api-management-400-19k5</link>
      <guid>https://dev.to/gravitee/write-your-own-policy-with-graviteeio-api-management-400-19k5</guid>
      <description>&lt;p&gt;The vast world of APIs is constantly evolving. This can be seen with the recent rise in popularity of event-driven architecture connected through modern event brokers (Kafka, Solace, etc.) and asynchronous web APIs. This transition from traditional, REST-dominated architectures with synchronous request-response style communication to mixed architectures dependent on both synchronous and asynchronous protocols requires a modern and versatile API Management solution: enter Gravitee API Management (APIM).&lt;/p&gt;

&lt;p&gt;As of Gravitee 4.0, APIM is an event-native API solution. This means Gravitee natively supports asynchronous web APIs and event brokers while still fully supporting synchronous request/response style APIs in a centralized control plane. Regardless of protocol, Gravitee can modify the behavior of the request or response through policies. Gravitee policies fall into several functional categories: security, transformation, restrictions, performance, routing, and monitoring &amp;amp; testing.&lt;/p&gt;

&lt;p&gt;Gravitee offers both a free Community Edition and paid Enterprise Edition of our platform. To learn more about what features are available in each edition, check out &lt;a href="https://documentation.gravitee.io/platform-overview/" rel="noopener noreferrer"&gt;our brand-new documentation site&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Gravitee’s protocol and policy support are powered through an extensible plugin system. So while there is built-in support for a number of protocols, policies (and more), the plugin system allows anyone to add new policies or even entrypoints/endpoints to APIM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/L4Bb7zCaP8FB5C769T/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/L4Bb7zCaP8FB5C769T/giphy.gif" alt="Amazing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes… I know, this opens up a brave new world of seemingly endless possibilities. But how to get started?&lt;/p&gt;

&lt;p&gt;In this article, I’ll teach you how to write your own custom policy using the plugin system, but first, a few housekeeping items.&lt;/p&gt;




&lt;h2&gt;
  
  
  🙋‍♂️ Who am I ?
&lt;/h2&gt;

&lt;p&gt;I am &lt;a href="https://twitter.com/ytvrnr" rel="noopener noreferrer"&gt;Yann Tavernier&lt;/a&gt; and I am a developer on the amazing APIM team at Gravitee. I'm delighted to walk you through the creation of a policy and how to efficiently test it!&lt;/p&gt;




&lt;h2&gt;
  
  
  📝 Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Your favorite Java IDE&lt;/li&gt;
&lt;li&gt;JDK 17&lt;/li&gt;
&lt;li&gt;Maven 3.8&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  👨‍🏫 About Gravitee
&lt;/h2&gt;

&lt;p&gt;If you want more information about the Gravitee platform, head over to the &lt;a href="https://documentation.gravitee.io/platform-overview/gravitee-essentials/overview" rel="noopener noreferrer"&gt;Gravitee Essentials&lt;/a&gt; section of our documentation site. &lt;/p&gt;




&lt;h2&gt;
  
  
  🔑 Key APIM components and concepts
&lt;/h2&gt;

&lt;p&gt;Before we start looking at Policy creation and testing, let's provide an overview of all of the key concepts and components that we'll be using in this blog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;APIM&lt;/strong&gt; is the API Management solution created by Gravitee.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APIM Gateway&lt;/strong&gt;: A reverse proxy layer that brokers, secures, and hardens access to APIs and data streams. It is the component of APIM responsible for handling requests from customers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APIM Management API (mAPI)&lt;/strong&gt;: A REST API used to configure and manage APIs and various Gravitee resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APIM Console&lt;/strong&gt;: A graphical user interface to configure Gateways, create APIs, design policies, and publish documentation. Every action in the APIM Management Console is tied directly to the mAPI.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key concepts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API Publisher&lt;/strong&gt; is a role type for APIM, representing the user of the company in charge of designing and publishing the APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API&lt;/strong&gt; is the representation of your backend inside APIM, and is composed of elements such as documentation, users, design, properties, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt; is the access and service layer on top of an API for consumer Applications. Consumer Applications need to subscribe to a plan to be able to consume an API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plugin&lt;/strong&gt; is a component that provide additional functionality to the Gravitee ecosystem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy&lt;/strong&gt; is a service or action that can be executed on an API request or response to perform checks, transformation or other services to it. As well as out of the box policies, you can also create your own. The functionality of the policy is enabled through plugins.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If you want more information about Gravitee, read this awesome &lt;a href="https://community.gravitee.io/c/dev-guide/23" rel="noopener noreferrer"&gt;Dev Guide&lt;/a&gt;! Even better, this guide is directly available on our community forum, so you can ask all your questions.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a policy?
&lt;/h3&gt;

&lt;p&gt;As mentioned earlier, a policy is essentially a service or action executed on a request, response or a message to perform things like transformations, rate limits, routing, monitoring &amp;amp; testing, etc.&lt;/p&gt;

&lt;p&gt;Technically speaking, a policy is nothing more than a piece of Java code consuming an execution context and returning a Completable (&lt;a href="https://github.com/gravitee-io/gravitee-gateway-api/blob/8b038648cf8588060a818ba2649e1e3df481c8d4/src/main/java/io/gravitee/gateway/jupiter/api/policy/Policy.java#L34" rel="noopener noreferrer"&gt;see here)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's take a look at the interface (Javadoc removed for readability purpose):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Policy&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nc"&gt;Completable&lt;/span&gt; &lt;span class="nf"&gt;onRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;HttpExecutionContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Completable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nc"&gt;Completable&lt;/span&gt; &lt;span class="nf"&gt;onResponse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;HttpExecutionContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Completable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nc"&gt;Completable&lt;/span&gt; &lt;span class="nf"&gt;onMessageRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;MessageExecutionContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Completable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nc"&gt;Completable&lt;/span&gt; &lt;span class="nf"&gt;onMessageResponse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;MessageExecutionContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Completable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ Note that, as we are in the reactive world, the policy implementation is used to build a reactive chain and this chain should only be executed when the Gateway subscribes to the policy. In short, this means your policy code must be written in the context of a Completable object creation.&lt;/p&gt;

&lt;p&gt;Here is a good example 💪&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Completable&lt;/span&gt; &lt;span class="nf"&gt;onRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;HttpExecutionContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Completable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromRunnable&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"X-DummyHeader"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"dummy"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a bad one 💥 (In the following example, the code will be executed before the subscription takes place which can have unintended side effects)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Completable&lt;/span&gt; &lt;span class="nf"&gt;onRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;HttpExecutionContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"X-DummyHeader"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"dummy"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 💥 Not to do&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Completable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  👩‍💻 Creating our own policy
&lt;/h2&gt;

&lt;p&gt;The best way to learn is by doing. I will talk you through all the steps needed to create a fully functional custom policy.  Let's create a &lt;strong&gt;🍕 Pizza Factory policy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExMTQwc3BhdWlpenJwMnpwaWdudmlxNjR0dmxid3NmbGFnOXFycmhxZiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/m54Uj4aKkoBpu/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExMTQwc3BhdWlpenJwMnpwaWdudmlxNjR0dmxid3NmbGFnOXFycmhxZiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/m54Uj4aKkoBpu/giphy.gif" alt="Pizza"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The goal of this policy is quite simple. It will use the request headers and payload to transform the request into a JSON pizza object. This will be duplicated on the response phase to return the created pizza Object to the user.&lt;/p&gt;

&lt;p&gt;The policy will be configurable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users can configure the crust and the sauce.&lt;/li&gt;
&lt;li&gt;To keep consumers of the pizza safe, we will add a toggle to forbid the word "pineapple" or "🍍". If the API request contains pineapple, then the Gateway will return a &lt;code&gt;406 Not Acceptable&lt;/code&gt;, else &lt;code&gt;500 Internal Server Error&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 In a more realistic policy, we would have the policy return a &lt;code&gt;400 Bad Request&lt;/code&gt; to follow standard HTTP error message semantics.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Some acceptance criteria
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Headers must follow this format: X-pizza-topping: #value#. You can use it multiple times to add as many toppings as necessary.&lt;/li&gt;
&lt;li&gt;Body must be an array of strings representing the toppings to add.&lt;/li&gt;
&lt;li&gt;If no &lt;code&gt;X-Pizza-Topping&lt;/code&gt; header is present and the body is empty, then a pizza object is not created and &lt;code&gt;X-Pizza: No Pizza&lt;/code&gt; header is added.&lt;/li&gt;
&lt;li&gt;If both &lt;code&gt;X-Pizza-Topping&lt;/code&gt; header and body payload are present, then both are used to compose the pizza object.&lt;/li&gt;
&lt;li&gt;If the body is not an array of strings, then it results in a &lt;code&gt;400 Bad Request&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The body of request or response will be replaced by the pizza object. We assume the content type will be &lt;code&gt;application/json&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🧪 Initialize it!
&lt;/h3&gt;

&lt;p&gt;To initialize your policy, simply fork or clone &lt;a href="https://github.com/gravitee-io/gravitee-policy-template" rel="noopener noreferrer"&gt;https://github.com/gravitee-io/gravitee-policy-template&lt;/a&gt;. &lt;br&gt;
This repository contains the necessary structure and minimum files needed to create a policy. You may need to update some dependencies (in pom.xml) to be consistent with versions used by APIM.&lt;/p&gt;

&lt;p&gt;Policies are written in Java and use Maven as the build tool.&lt;/p&gt;

&lt;p&gt;Let's take a close look at the structure of the policy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;README.adoc&lt;/code&gt; is here to explain the purpose of your policy, how to use it and the error cases. 
💡 This file is used in the Management Console UI of Gravitee APIM as in-app documentation for the users of the platform; therefore, take care to ensure that the README is clear and comprehensive.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pom.xml&lt;/code&gt; contains information about the project and configuration details used by Maven to build the project. This base comes with the minimal set of dependencies to develop and build your policy.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/assembly&lt;/code&gt; is used by maven-assembly-plugin to generate the zip of the policy with the right structure. ⚠️ You do not need to modify this file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/main/java&lt;/code&gt; will contain the policy code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/main/resources/plugin.properties&lt;/code&gt; is the manifest of the policy. It contains informations such as the policy's id, name and icon. For the Pizza Policy, &lt;code&gt;plugin.properties&lt;/code&gt; file will look like this:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;pizza-factory&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Pizza&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;${project.version}&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;${project.description}&lt;/span&gt;
&lt;span class="py"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;io.gravitee.policy.pizza.PizzaPolicy&lt;/span&gt;
&lt;span class="py"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;policy&lt;/span&gt;
&lt;span class="py"&gt;category&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;transformation&lt;/span&gt;
&lt;span class="py"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;pizza.svg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;src/main/resources/schemas/schema-form.json&lt;/code&gt; is the representation of the configuration of your policy. It is used to generate the schema and validate the creation of a policy whether using the APIM Management UI or the Management API directly.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/test/java&lt;/code&gt; and &lt;code&gt;src/test/resources&lt;/code&gt; are here for testing purposes. Here, you can find a &lt;code&gt;TemplatePolicyIntegrationTest&lt;/code&gt; test class that has already been  implemented. We will discuss it in more detail later, but essentially, it allows for easy creation of unit tests to verify your policy behaves as expected. This is done by deploying an API using this policy on an in-memory Gateway and then calls the API to verify the response matches the expectation.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🚀 Let's develop it
&lt;/h2&gt;

&lt;p&gt;I will not detail every step, but instead focus on the steps required to develop a policy in Gravitee.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/qdnMr2j2anHsLTv5TO/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/qdnMr2j2anHsLTv5TO/giphy.gif" alt="Work smarter"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  📤 The request phase
&lt;/h3&gt;

&lt;p&gt;Let's go into it. As a reminder, our policy aims to transform the body into a JSON pizza object depending on incoming request headers and payload.&lt;br&gt;
We will modify the &lt;code&gt;onRequest&lt;/code&gt; method in this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Override&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Completable&lt;/span&gt; &lt;span class="nf"&gt;onRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpExecutionContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;onBody&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maybeBody&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;doSomethingHere&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;HttpExecutionContext&lt;/code&gt; allows developers to access different objects tied to API transaction itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;request()&lt;/code&gt;: allows access to the current request which provides accessors to &lt;code&gt;headers&lt;/code&gt;, &lt;code&gt;pathParameters&lt;/code&gt;, &lt;code&gt;HTTP method&lt;/code&gt;, &lt;code&gt;pathInfo&lt;/code&gt;, &lt;code&gt;host&lt;/code&gt;, etc. It also provides methods to manipulate the body (&lt;code&gt;onBody&lt;/code&gt;) or to interrupt the call (&lt;code&gt;interruptWith&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;response()&lt;/code&gt;: the same thing as &lt;code&gt;request()&lt;/code&gt; except you don't have any request related information.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getAttribute(String attribute)&lt;/code&gt;: allows you to manipulate an attribute that has been stored in the context of the API transaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 The &lt;code&gt;onBody&lt;/code&gt; method lets you manipulates a &lt;code&gt;Maybe&amp;lt;Buffer&amp;gt;&lt;/code&gt;. This can handle the uncertainty inherent in every API request: maybe the request has a body, maybe not.&lt;/p&gt;

&lt;h4&gt;
  
  
  🍕 Creating a pizza
&lt;/h4&gt;

&lt;p&gt;First, we will create the core feature of our policy: the &lt;code&gt;createPizza&lt;/code&gt; method. As inputs, it needs the incoming payload and headers, and will return a Buffer: our pizza object. As we extract the body and headers from the context object, we do not need to stay in the reactive programming style, we will see later how to do the link.&lt;/p&gt;

&lt;p&gt;Our method would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Buffer&lt;/span&gt; &lt;span class="nf"&gt;createPizza&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Buffer&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpHeaders&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;toppings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extractToppings&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;verifyPineapple&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Buffer&lt;/span&gt; &lt;span class="n"&gt;pizzaObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createPizzaObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pizzaObject&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some information: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;extractToppings(Buffer body, HttpHeaders headers)&lt;/code&gt; is responsible for the following:

&lt;ul&gt;
&lt;li&gt;extracting the toppings from headers (&lt;code&gt;X-Pizza-Topping&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;extracting the toppings from body. In this case, body must be a valid json array of strings, or else a &lt;code&gt;NotStringArrayException&lt;/code&gt; will be thrown.&lt;/li&gt;
&lt;li&gt;returning the set of toppings extracted from body and headers.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If the list of toppings is empty, the pizza is not created and an empty buffer is returned.&lt;/li&gt;
&lt;li&gt;Next, comes the pineapple case. If policy is configured to refuse pineapple, and toppings list contains &lt;code&gt;pineapple&lt;/code&gt; or &lt;code&gt;🍍&lt;/code&gt;, then a &lt;code&gt;PineappleForbiddenException&lt;/code&gt; would be thrown.&lt;/li&gt;
&lt;li&gt;Finally, the method creates and returns a pizza object which is just the JSON representation of the pizza from the configured &lt;code&gt;crust&lt;/code&gt;, &lt;code&gt;sauce&lt;/code&gt; and extracted toppings. A &lt;code&gt;PizzaProcessingException&lt;/code&gt; could be thrown in case of mapping issue.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This code is fairly straightforward and does not require any knowledge of reactive programming.&lt;/p&gt;

&lt;h4&gt;
  
  
  🍽️ Serving the pizza
&lt;/h4&gt;

&lt;p&gt;However, the &lt;code&gt;createPizza&lt;/code&gt; method now needs to be transformed. We have to integrate our &lt;code&gt;createPizza&lt;/code&gt; method into the reactive chain.&lt;/p&gt;

&lt;p&gt;The reactive world, and more precisely &lt;a href="https://github.com/ReactiveX/RxJava" rel="noopener noreferrer"&gt;RxJava 3&lt;/a&gt; in our case, does not directly manipulate &lt;code&gt;Buffer&lt;/code&gt;, it manipulates reactive objects. Those objects implements the Reactive Pattern for different cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Single&lt;/code&gt; for a single value response&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Maybe&lt;/code&gt; for a single value, no value or an exception&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Completable&lt;/code&gt; for a deferred computation without any value, but only indication for completion or exception&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Flowable&lt;/code&gt; to consume reactive dataflows&lt;/li&gt;
&lt;li&gt;And many others.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember, our method returns a &lt;code&gt;Buffer&lt;/code&gt;: an empty buffer if there are no toppings, or the pizza object as a buffer.&lt;br&gt;
This is a perfect use case for the &lt;code&gt;Maybe&lt;/code&gt; reactive object:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If there are no toppings, return &lt;code&gt;Maybe.empty()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Else, return &lt;code&gt;Maybe.just(pizzaObject)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The method now looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Buffer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;createPizza&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Buffer&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpHeaders&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;toppings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extractToppings&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;empty&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;verifyPineapple&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Buffer&lt;/span&gt; &lt;span class="n"&gt;pizzaObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createPizzaObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;just&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pizzaObject&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we are able to use our method in a reactive way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Override&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Completable&lt;/span&gt; &lt;span class="nf"&gt;onRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpExecutionContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onBody&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maybeBody&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;maybeBody&lt;/span&gt;
                &lt;span class="c1"&gt;// If no body, then use an empty buffer&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;defaultIfEmpty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="c1"&gt;// Create a pizza from body and headers&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flatMapMaybe&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;createPizza&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt;
                &lt;span class="c1"&gt;// If no pizza has been created, then handle the case&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;switchIfEmpty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handleNoPizza&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt;
                &lt;span class="c1"&gt;// Manage errors&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onErrorResumeNext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handleError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me provide some further explanation of these changes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;onBody&lt;/code&gt; lets us manipulate a &lt;code&gt;Maybe&amp;lt;Buffer&amp;gt;&lt;/code&gt;. This body can indeed be empty if the user provides toppings only using headers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The first step is to have something to manipulate. Using &lt;code&gt;maybeBody.defaultIfEmpty(Buffer.buffer())&lt;/code&gt; provides an empty buffer to be used in subsequent steps. If we've kept an empty maybe, then we could not continue to the next steps in the reactive chain. There must be something to compute.&lt;/li&gt;
&lt;li&gt;Now, we have a &lt;code&gt;Single&amp;lt;Buffer&amp;gt;&lt;/code&gt;. Thanks to the &lt;code&gt;flatMapMaybe()&lt;/code&gt; operator, we can use the Buffer and return a &lt;code&gt;Maybe&lt;/code&gt; object. That's exactly what we have done with &lt;code&gt;Maybe&amp;lt;Buffer&amp;gt; createPizza(Buffer body, HttpHeaders header)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;With the &lt;code&gt;switchIfEmpty()&lt;/code&gt; operator, we can handle the case of an empty pizza, by adding a &lt;code&gt;X-Pizza: not-created&lt;/code&gt; header with this method:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Buffer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handleNoPizza&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpHeaders&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromCallable&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;X_PIZZA_HEADER&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;NOT_CREATED&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;});&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Finally, we handle the errors that might have ocurred during the process with the &lt;code&gt;onErrorResumeNext()&lt;/code&gt; operator. 
Let's look at the error handling in more detail.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  💥 Managing errors
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;onErrorResumeNext()&lt;/code&gt; operator allows you to resume the flow with a &lt;code&gt;Maybe&lt;/code&gt; object that is returned for a particular failure. In other words, it allows to properly manage the error cases that can occur in the reactive chain.&lt;/p&gt;

&lt;p&gt;Our requirements were about returning particular HTTP status codes depending on whether we are in request or response phase, and provide details on the type of error:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;REQUEST: 

&lt;ul&gt;
&lt;li&gt;PineappleForbiddenException: &lt;code&gt;406 - Not Acceptable&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;All other exceptions: &lt;code&gt;400 - Bad Request&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;RESPONSE: 

&lt;ul&gt;
&lt;li&gt;All exceptions: &lt;code&gt;500 - Internal Server Error&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;HttpExecutionContext&lt;/code&gt; contains an interesting method: &lt;code&gt;interruptBodyWith(ExecutionFailure failure)&lt;/code&gt;. It allows the developer to fail the current request/response flow with an &lt;code&gt;ExecutionFailure&lt;/code&gt; object.&lt;br&gt;
This objects can be configured with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(required) the HTTP status code to return to the user&lt;/li&gt;
&lt;li&gt;a message to be returned as the body&lt;/li&gt;
&lt;li&gt;a key that can referenced by the Response Template feature of APIM&lt;/li&gt;
&lt;li&gt;and some other features we won't dive into here&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The error management code is pretty straightforward to write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Throwable&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Buffer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpExecutionContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isOnRequest&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"It was not possible to create the pizza because: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isOnRequest&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;PineappleForbiddenException&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;interruptBodyWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ExecutionFailure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpStatusCode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NOT_ACCEPTABLE_406&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;PIZZA_ERROR_KEY&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
            &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;interruptBodyWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ExecutionFailure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isOnRequest&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nc"&gt;HttpStatusCode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BAD_REQUEST_400&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;HttpStatusCode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INTERNAL_SERVER_ERROR_500&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;PIZZA_ERROR_KEY&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🚦 Test your policy
&lt;/h3&gt;

&lt;p&gt;Gravitee APIM comes with what we call the Gateway Testing SDK.&lt;/p&gt;

&lt;p&gt;This library can be seen as a &lt;a href="https://junit.org/junit5/docs/current/user-guide/#extensions" rel="noopener noreferrer"&gt;JUnit 5 extension&lt;/a&gt; which allow the developer to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write tests as regular JUnit 5 tests&lt;/li&gt;
&lt;li&gt;Run an in-memory gateway (and configure it as needed)&lt;/li&gt;
&lt;li&gt;Deploy inline plugins (directly from code)&lt;/li&gt;
&lt;li&gt;Do real call against the gateway to verify it behaves as expected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our present case, we will want to validate that if we call an API using the &lt;code&gt;Pizza Factory Policy&lt;/code&gt;, then we have the expected behavior in term of returned object or error handling.&lt;/p&gt;

&lt;p&gt;Some cases to be tested (on both request and response): &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Should not create a pizza when no topping provided&lt;/li&gt;
&lt;li&gt;Should create a pizza when toppings comes from headers&lt;/li&gt;
&lt;li&gt;Should create a pizza when toppings comes from body&lt;/li&gt;
&lt;li&gt;Should create a pizza when toppings comes from headers and body&lt;/li&gt;
&lt;li&gt;Should not create a pizza when toppings contains pineapple and it's forbidden&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Test preparation
&lt;/h4&gt;

&lt;p&gt;APIs are deployed from a JSON definition. You can learn more about Gravitee's API definition &lt;a href="https://documentation.gravitee.io/apim/overview/gravitee-api-definitions-and-execution-engines" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is the policy configuration portion of an API definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Pizza Factory on request"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Create your pizza from request headers!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"policy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pizza-factory"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"configuration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"crust"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Pan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"sauce"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TOMATO"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"pineappleForbidden"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This JSON string will be used to deploy the test API on the testing Gateway, and will allow us to call this API for testing.&lt;/p&gt;

&lt;p&gt;Next, we need to create a test class. APIM team uses the &lt;code&gt;IntegrationTest&lt;/code&gt; suffix to distinguish tests using the SDK from regular unit tests.&lt;/p&gt;

&lt;p&gt;Here is the minimal code needed to do to run a test with the SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@GatewayTest&lt;/span&gt;
&lt;span class="nd"&gt;@DeployApi&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/apis/pizza-api.json"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PizzaPolicyIntegrationTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractPolicyTest&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PizzaPolicy&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;PizzaPolicyConfiguration&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;configureEntrypoints&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;EntrypointConnectorPlugin&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?,&lt;/span&gt; &lt;span class="o"&gt;?&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;entrypoints&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;entrypoints&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;putIfAbsent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http-proxy"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;EntrypointBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http-proxy"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpProxyEntrypointConnectorFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;configureEndpoints&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;EndpointConnectorPlugin&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?,&lt;/span&gt; &lt;span class="o"&gt;?&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;endpoints&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;endpoints&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;putIfAbsent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http-proxy"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;EndpointBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http-proxy"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpProxyEndpointConnectorFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;should_create_pizza_with_header_toppings_on_request&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpClient&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// We will focus on the test case later&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;@GatewayTest&lt;/code&gt; is a meta-annotation which marks the class as testable with the SDK. It will run the necessary extensions to run the Gateway and initialize components&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@DeployApi&lt;/code&gt; deploys an API based on its definition. You can also pass an array of APIs to deploy, where each API must have a distinct name and entrypoint.

&lt;ul&gt;
&lt;li&gt;Used at class level, it will deploy the APIs once for the Gateway instance, meaning all the methods annotated with &lt;code&gt;@Test&lt;/code&gt; will be able to call those APIs.&lt;/li&gt;
&lt;li&gt;Used at method level, it will deploy the APIs for the lifetime of the test method and then it will be undeployed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AbstractPolicyTest&amp;lt;PizzaPolicy, PizzaPolicyConfiguration&lt;/code&gt; is an abstract class allowing you to directly register your policy on the Gateway. You can also extends &lt;code&gt;AbstractGatewayTest&lt;/code&gt; and register your policy thanks to &lt;code&gt;AbstractGatewayTest#configurePolicies(Map&amp;lt;String PolicyPlugin policies)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;configureEntrypoints(Map&amp;lt;String, EntrypointConnectorPlugin&amp;lt;?, ?&amp;gt;&amp;gt; entrypoints)&lt;/code&gt; and &lt;code&gt;configureEndpoints(Map&amp;lt;String, EndpointConnectorPlugin&amp;lt;?, ?&amp;gt;&amp;gt; endpoints)&lt;/code&gt; allow the developer to register entrypoint and endpoint plugins. In this case, &lt;code&gt;http-proxy&lt;/code&gt; connectors are registered so that the API can be deployed as a &lt;code&gt;proxy&lt;/code&gt; api.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;💡 You can learn more about the difference between Proxy and Message Gateway APIs &lt;a href="https://documentation.gravitee.io/apim/guides/create-apis/how-to/v4-api-creation-wizard#step-2-entrypoints" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Writing a test
&lt;/h4&gt;

&lt;p&gt;You may have noticed in the previous example that an &lt;code&gt;HttpClient&lt;/code&gt; is injected as a parameter of the test method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;should_create_pizza_with_header_toppings_on_request&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpClient&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is injected to make your life easier. An important thing to understand is that the Gateway is started on a random available port, and the same applies to the started &lt;code&gt;Wiremock&lt;/code&gt; used as endpoint.&lt;/p&gt;

&lt;p&gt;When deploying an API, the SDK will update the &lt;code&gt;localhost:8080&lt;/code&gt; endpoints with by the right port and thereby allowing requests to reach &lt;code&gt;Wiremock&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;HttpClient&lt;/code&gt;, in the same way, is configured to reach directly to the Gateway on the right port.&lt;/p&gt;

&lt;p&gt;So, we now want to test if a pizza is created from toppings provided as a header when the Pizza Policy is configured on request phase. API is configured to be reached on &lt;code&gt;/test&lt;/code&gt; path and to contact a backend on &lt;code&gt;/endpoint&lt;/code&gt; path.&lt;/p&gt;

&lt;p&gt;Here is the code of the test, with comments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Should create pizza when toppings provided from headers"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;should_create_pizza_with_header_toppings_on_request&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpClient&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. Prepare wiremock endpoint to answer with a `200 - OK` and an empty body when `/endpoint` is reached&lt;/span&gt;
    &lt;span class="n"&gt;wiremock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stubFor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/endpoint"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;willReturn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. Use the HttpClient to call your deployed API, configured with `/test` as context-path&lt;/span&gt;
    &lt;span class="n"&gt;httpClient&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rxRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpMethod&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GET&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/test"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;// 2.1 Send the request to the gateway, with toppings header: `x-pizza-topping:peperoni,cheddar`&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flatMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;putHeader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;X_PIZZA_HEADER_TOPPING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"peperoni"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cheddar"&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="na"&gt;rxSend&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="c1"&gt;// 2.2 Verify the response status is the expected one and return the body&lt;/span&gt;
       &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flatMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;isEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpStatusCode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;OK_200&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;})&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;awaitDone&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;TimeUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SECONDS&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;// 2.3 Verify the call is complete, and that the body is an empty buffer   &lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertComplete&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertNoErrors&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Verify the wiremock endpoint has been called&lt;/span&gt;
    &lt;span class="c1"&gt;//    - on `/endpoint`&lt;/span&gt;
    &lt;span class="c1"&gt;//    - with header `x-pizza:created`&lt;/span&gt;
    &lt;span class="c1"&gt;//    - with the expected pizza object&lt;/span&gt;
    &lt;span class="n"&gt;wiremock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;verify&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;getRequestedFor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urlPathEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/endpoint"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
           &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withHeader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;X_PIZZA_HEADER&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;equalTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;CREATED&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
           &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withRequestBody&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;equalTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{\"crust\":\"Pan\",\"sauce\":\"TOMATO\",\"toppings\":[\"peperoni\",\"cheddar\"]}"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🏆 That's it, you know how to test a policy! You just need to implements the other test cases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/7MZ0v9KynmiSA/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/7MZ0v9KynmiSA/giphy.gif" alt="As expected"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the README of the SDK &lt;a href="https://github.com/gravitee-io/gravitee-api-management/tree/22c93ebc2b7c2ab44d3536c67a9097d7877fbcef/gravitee-apim-gateway/gravitee-apim-gateway-tests-sdk" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more examples of tests, you can take a look &lt;a href="https://github.com/gravitee-io/gravitee-api-management/tree/22c93ebc2b7c2ab44d3536c67a9097d7877fbcef/gravitee-apim-integration-tests" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🍕 Use it!
&lt;/h2&gt;

&lt;p&gt;Now, it's time to use your policy.&lt;br&gt;
You first need to build the ZIP file that will be deployed on the Management API and on the Gateway of APIM.&lt;/p&gt;

&lt;p&gt;Thankfully, this is quite simple. Just run &lt;code&gt;mvn clean install&lt;/code&gt;. (The policy is preconfigured to apply a prettier check and to enforce code formatting. If you have any issues, you may need to manually run &lt;code&gt;mvn prettier:write&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This generates a ZIP file containing all the necessary assets for the policy to be used by APIM. This ZIP file can be found in the &lt;code&gt;target&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Deploying a plugin is as easy as copying the plugin archive into the dedicated directory. By default, you need to deploy the ZIP in &lt;code&gt;${GRAVITEE_HOME}/plugins&lt;/code&gt; (more information &lt;a href="https://documentation.gravitee.io/apim/overview/plugins#deployment" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;⚠️ You need to restart the Management API and Gateway for the plugin to be loaded.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F48b0wk2tq2t2qx9fb3e9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F48b0wk2tq2t2qx9fb3e9.png" alt="Configuration of the Policy in Policy Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flria60jsbt86fw8qjlr7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flria60jsbt86fw8qjlr7.png" alt="View of the Policy in Policy Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 What about v2 APIs?
&lt;/h2&gt;

&lt;p&gt;For existing users of Gravitee APIM, you probably have some "v2" APIs.&lt;br&gt;
Those APIs were running with the legacy engine, and policies were written in a different format than what was shown in this blog.&lt;/p&gt;

&lt;p&gt;Lucky for you, you can use policies written in 4.0.0 style with existing v2 APIs, 4.0 was designed with backward compatibility in mind. To do so, "v4 Emulation mode" must be enabled by setting the &lt;code&gt;executionMode&lt;/code&gt; field of your API definition to: &lt;code&gt;v4-emulation-engine&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;💡 You can learn more about the different Gravitee execution engines, API definitions, and emulation mode &lt;a href="https://documentation.gravitee.io/apim/overview/gravitee-api-definitions-and-execution-engines" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ To wrap up
&lt;/h2&gt;

&lt;p&gt;In this blog, we just saw how to write, test and deploy a simple custom policy to explore the extensible nature of Gravitee APIM. You can find the complete policy on the &lt;a href="https://github.com/gravitee-io-community/gravitee-policy-pizza" rel="noopener noreferrer"&gt;Gravitee Pizza Policy repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If this blog inspired you to build your own policy, you can get started quickly by forking the &lt;a href="https://github.com/gravitee-io/gravitee-policy-template" rel="noopener noreferrer"&gt;Policy Template&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All are welcome to get involved in the Gravitee Community. From everything to submitting pull requests in the &lt;a href="https://github.com/gravitee-io/gravitee-api-management" rel="noopener noreferrer"&gt;APIM repo&lt;/a&gt; to getting involved in our &lt;a href="https://community.gravitee.io/" rel="noopener noreferrer"&gt;Gravitee Community Discourse&lt;/a&gt;, we'd love to have you join our vibrant community.&lt;/p&gt;

&lt;p&gt;Please don't hesitate to ask for support on our community discourse 🤝, we are happy to help!&lt;/p&gt;

</description>
      <category>graviteeio</category>
      <category>api</category>
      <category>opensource</category>
      <category>apim</category>
    </item>
    <item>
      <title>What is API Management and how it helps you get the most out of your APIs</title>
      <dc:creator>lju-lazarevic</dc:creator>
      <pubDate>Thu, 16 Jun 2022 17:25:59 +0000</pubDate>
      <link>https://dev.to/gravitee/what-is-api-management-and-how-it-helps-you-get-the-most-out-of-your-apis-5bk2</link>
      <guid>https://dev.to/gravitee/what-is-api-management-and-how-it-helps-you-get-the-most-out-of-your-apis-5bk2</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aF7cAwbZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/217qqw8ovm3r1fq7nr03.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aF7cAwbZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/217qqw8ovm3r1fq7nr03.jpg" alt="John Barkiple on Unsplash" width="640" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The explosion of APIs
&lt;/h2&gt;

&lt;p&gt;We are witnessing a huge explosion of APIs, largely driven by a number of factors, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Breaking up the monolith - taking large applications with many services and breaking up those interdependencies into individual, easier to develop and manage standalone services&lt;/li&gt;
&lt;li&gt;Faster innovation - understanding the data demand and providing APIs that support these demands, promoting fail fast and trialing proofs of concept&lt;/li&gt;
&lt;li&gt;Resource sharing - democratizing data and services across departments in an organization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this immense growth of APIs comes great opportunities, but also, there are some challenges as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  The challenges of APIs
&lt;/h2&gt;

&lt;p&gt;There are a number of challenges facing organizations as the number of APIs that they develop and deploy increase. Let’s take a look at some of them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Discoverability&lt;/strong&gt;&lt;br&gt;
How do developers find these APIs? How do they discover what is available? Where can they locate the documentation? How do they subscribe to the APIs? Ultimately, what does that developer experience look like? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security and performance&lt;/strong&gt;&lt;br&gt;
Do you really want to tightly couple authentication and authorization to each API, along with its business logic? How are you going to manage policies on who can access what? Are these policies on an API by API basis, or organizational wide? What about protecting the backend applications? How do you prevent excessive requests to them? What about managing caching and other policies that will not only protect your applications, but also improve performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Governance&lt;/strong&gt;&lt;br&gt;
How do ensure the processes around API design and creation are being followed? For example, are the naming conventions being followed? Are the right stakeholders involved? How are existing services and functions being used?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monitoring and alerting&lt;/strong&gt;&lt;br&gt;
Who is using your APIs? How do you know when and where they’re being accessed? Are they being used at all?! Are your APIs and the systems behind them still responsive? How do you check for unusual or suspicious behavior? &lt;/p&gt;

&lt;h2&gt;
  
  
  Changing the mindset
&lt;/h2&gt;

&lt;p&gt;So how do we address and support the rise of APIs?. First of all, we need to start thinking about APIs as a product. Historically, the attention would be focussed on building the application itself, and then addressing how the application would work with other ones would come last. Changing that mindset to thinking about the API as a product, and designing the API first brings a number of benefits. The journey starts with considering who is going to use the API, what services will it be providing access to, and so forth. This practice of putting the API development ahead of the rest of the application is called API First, which we will cover shortly.&lt;/p&gt;

&lt;p&gt;Another element to support the rise of APIs is through API Management. API Management allows us to remove the complexity around API development, so that our concern is centered around the building of the API and the supporting business logic, and let something else deal with the security, the governance, the lifecycle management, and so forth.&lt;/p&gt;

&lt;h2&gt;
  
  
  API and Design First
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rJTs_5bc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5lhcvywhm4wxfjol9o0s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rJTs_5bc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5lhcvywhm4wxfjol9o0s.png" alt="Design First flow" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;API First introduces the mindset of treating your APIs as products. This involves considering the APIs to have equal importance as the application itself. They are viewed as the doorway to the products and services your project is going to provide, and become the first consideration. Regardless of what happens with the project, ultimately everything is going to be using the APIs, so the thinking starts there. It is the component that’s most likely to change if an application, ‘bottom-up approach’ is taken instead. API First allows us to get feedback from all of the key stakeholders, as well as iterating on designs quickly and getting buy-in. Once there is agreement from across the board, everything else can follow in turn. &lt;/p&gt;

&lt;p&gt;However, API first is not designed first. There are subtle differences between Code First and Design First in the terms of API first. Code First delivers the API first, with all other activities based on consuming the API coming after. Design First seeks to get a consensus on the API contract, allowing for parallel development based on what the API will look like. My colleague Lorie Pisicchio goes into more detail on this, based on her &lt;a href="https://medium.com/graviteeio/why-design-first-when-building-apis-fc5d9cf406c4"&gt;fantastic blog&lt;/a&gt;, as well as a talk she did for &lt;a href="https://youtu.be/0meMI_6CBR0"&gt;API World 2021&lt;/a&gt;. Do check them out!&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing API Management
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4yXkCxMp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wxy5qkv4g5rbn5xud88c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4yXkCxMp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wxy5qkv4g5rbn5xud88c.png" alt="API Management lifecycle" width="639" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;API management is a methodology to manage the complete lifecycle of APIs. As well as being a methodology, there are platforms and tools to assist in its application and governance.&lt;/p&gt;

&lt;p&gt;There can sometimes be confusion between API Management and an API Gateway. An API Gateway brokers the connection between a client and the API and its backend. It will apply any policies on the request and response flows, such as rate limiting, throttling and transformation. API Management would, as part of the process, determine what policies should be applied, as well as maintaining the historical records of changes made as part of the API lifecycle. &lt;/p&gt;

&lt;p&gt;A simple analogy would be as follows - imagine an automated rotating door (the API) between the outside and inside a building, housed within a frame with the mechanics (the API Gateway). The door may revolve at a certain speed (a throttling policy) along with other constraints, however the decision for what rate the door will rotate, and that there’s a rotating door rather than an automatic sliding door, or a hinged, manual door, as well as how it would be installed, and what processes are used to maintain it, was made at the time of building planning (API Management). A decision could be made to speed up or slow down the doors could be made (API Management), as well as whether to remove the doors completely and use a different type, including overseeing the removal and installation (API Management).&lt;/p&gt;

&lt;p&gt;So let’s investigate what API Management offers us in terms of dealing with APIs. First of all, there's no point in having an API if a developer can't find it. API Management helps us to not only create APIs, but also publish the APIs and make them discoverable to developers, as well as providing the documentation and other associated information. We can also use information as the APIs are being subscribed and used to nurture the developer community, as well as understanding how they’re using them, getting their feedback, and ultimately, improving the developer experience.&lt;/p&gt;

&lt;p&gt;API management also helps enforce the use of policies and controlling access to APIs. So we can deal with whether a client has been authorized or authenticated to use it.We can apply performance policies such as rate limiting and throttling to not only protect against malicious behavior, but to also look after the backend systems. &lt;/p&gt;

&lt;p&gt;We can monitor and analyze how APIs are being used, if they’re being used, as well as checking on the health of our APIs. We can also proactively look out for unusual or suspicious behavior and act accordingly, triggering alerts as appropriate. &lt;/p&gt;

&lt;p&gt;Last but not least, API management can help us with governance, for example company wide policies, naming conventions, design conventions and so forth. &lt;/p&gt;

&lt;p&gt;All in all, API management relieves us from the infrastructure logistics involved in making APIs available, and allows us to apply our focus on the business logic contained within the API management itself. Let’s now have a look at an example API Management platform, Gravitee, an open source product. &lt;/p&gt;

&lt;h2&gt;
  
  
  Overview of an example API Management platform
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UHPRAM2f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qf9atohwyyq5go6bcmvy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UHPRAM2f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qf9atohwyyq5go6bcmvy.png" alt="Gravitee API Management architecture" width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gravitee.io"&gt;Gravitee&lt;/a&gt; is a &lt;a href="https://github.com/gravitee-io/gravitee-api-management"&gt;fully open source&lt;/a&gt;, low code, highly customisable API management platform, with a highly performant API gateway. It is a Java based product using the &lt;a href="https://vertx.io/"&gt;Vert.x framework&lt;/a&gt;. It uses the concepts of plugins to manage policies, including security, data transformation, protocol mediation, monitoring, authentication, performance and so forth. There are over 100 plugins available, and should you happen to not find the one you’re looking for, you can write your own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developer Portal
&lt;/h3&gt;

&lt;p&gt;The developer portal is where developers can explore, research and subscribe to your APIs.  They are able to try out the API's, read the documentation, as well as providing reviews and feedback. &lt;/p&gt;

&lt;h3&gt;
  
  
  API Console
&lt;/h3&gt;

&lt;p&gt;This is where the API owner can manage the whole lifecycle of the API from design, deployment, policies to apply, API deprecation and disablement. They are also able to monitor API activity. There is also an API available for CI/CD deployments and other automation. &lt;/p&gt;

&lt;h3&gt;
  
  
  API Gateway
&lt;/h3&gt;

&lt;p&gt;The Gateway is responsible for being the doorway between the client and the API. It will apply the policies as dictated by the API Console, and all of the rules applied will be deployed onto the Gateway by the Console. &lt;/p&gt;

&lt;p&gt;If you’d like to have a go at getting the Gravitee APIM platform up and running on your local machine, &lt;a href="https://medium.com/graviteeio/getting-gravitee-io-api-management-platform-up-and-running-on-a-local-machine-9408d07221e6"&gt;this blog post&lt;/a&gt; provides you with step by step instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Hopefully, you now have a good overview of what API Management does, the difference between API Management and API Gateways, as well as the opportunity to get an example of an API Management platform that can support this practice.If you’ve got any questions about either Gravitee, or API Management in general, do reach out to us on our &lt;a href="https://community.gravitee.io"&gt;community forum&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>api</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Explaining API Management to your mom</title>
      <dc:creator>Antoine Mouliere</dc:creator>
      <pubDate>Wed, 08 Jun 2022 08:21:15 +0000</pubDate>
      <link>https://dev.to/gravitee/explaining-api-management-to-your-mom-glo</link>
      <guid>https://dev.to/gravitee/explaining-api-management-to-your-mom-glo</guid>
      <description>&lt;p&gt;In this blog post we’re going to cover what are all the parts of API Management using an example based on a restaurant. We all too often forget that not everybody is technically-minded, and sometimes it’s great to take a step back and find common language to explain certain terminology. &lt;/p&gt;

&lt;h2&gt;
  
  
  So what’s your job again?
&lt;/h2&gt;

&lt;p&gt;Nice to meet you all, I’m Antoine, a Product Owner of the &lt;a href="https://www.gravitee.io/" rel="noopener noreferrer"&gt;Gravitee.io&lt;/a&gt; API Management solution, you can find me on our &lt;a href="https://community.gravitee.io/" rel="noopener noreferrer"&gt;community forum&lt;/a&gt;. One of the biggest challenges I’ve met so far is to answer my mom’s question, “What’s your job all about?”. &lt;/p&gt;

&lt;p&gt;I guess my normal answer would be, “Product Owner of largest Open Source API Management mom. We’re creating software to build, monitor and secure APIs! Did I also mention it’s Open Source? Isn’t that awesome!?”. &lt;/p&gt;

&lt;p&gt;However, that didn’t seem to convince her that much, nor did it help her understand what I'm doing with my day. But she’s my mom, so she loves me anyway and she’ll get along with “my son works in IT”. I’m looking for a change - I don’t want to fix printers anymore, and I guess my mom deserves to understand what I'm working on. A thought to consider, do we really understand our areas of expertise if we can’t even explain it to our mom, or a six-year old for that matter? &lt;/p&gt;

&lt;p&gt;And so comes the tricky question: how do I explain what API management is to my mom? I’ve been trying to figure out some sort of approach. I’ve been:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Diving into my school archives to find relevant resources&lt;/li&gt;
&lt;li&gt;Exploring howtocode.com&lt;/li&gt;
&lt;li&gt;Looking at the basic tenets of IT, and so on. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do I really want to give my mom a four-hours lecture on the basics of APIs? I’m not so sure. Does she want to listen to a four-hour lecture? Hmmm not sure either. Is this going to work with a six year old? Definitely not! &lt;/p&gt;

&lt;p&gt;What’s needed is something that’s tangible, based on a real-life situation that can aptly describe the purpose of API Management. So, let’s run with the example of a restaurant - everyone can relate to a restaurant - even my two-year old son has mastered the art of ordering fries. &lt;/p&gt;

&lt;h2&gt;
  
  
  The restaurant analogy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qp4hz9ni8qa5a6x0qok.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qp4hz9ni8qa5a6x0qok.png" alt="Restaurant illustration of API Management"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Photo by Jeremy Bishop on Unsplash, and as you can see I’m not a designer ;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client/Customer&lt;/strong&gt; - It’s rather funny that we use the same term in API Management! Coincidence - I don’t think so!  The client application is what sends a request. How would they go about making their request? Are you going to a restaurant and asking for whatever you want? Most certainly not, you will ask for a menu. &lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;API Specification&lt;/strong&gt; or definition is the equivalent of a menu in a restaurant. It contains a list of what you can order, and a description of what you can expect for each item.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;backend&lt;/strong&gt; of your application is the equivalent of the restaurant’s kitchen. The kitchen will prepare your meal, dish it out and nicely present it on a plate, and with a bit of luck, give you exactly what you ordered. This is the backend’s responsibility - to provide you the information you need, apply any processing to the data, and maybe request more information from other sources. The kitchen would handle the food processing, for example freezing, defrosting, slicing, dicing and cooking. The kitchen may need to request more ingredients. All of this information and processing going on, you, as a client or customer, do not need to know about, nor should you care about it for you to receive your ordered dish! &lt;/p&gt;

&lt;p&gt;So we now have a customer (client), a menu (API specification) and a kitchen (backend system). We are missing one key element here. How does the kitchen know what you want? Sure, you could go into the kitchen yourself and directly ask the chef, but he’s nervous, and doesn’t really want to be speaking to lots of people during the dinner rush hour. Also, it’s not particularly hygienic to have people coming into a kitchen, nor is it practical for 30-odd patrons to walk in, shouting out their preferred order. So, how do we deal with taking the order from the party of 10 who’ve just turned up, as well as trying to keep the children across the room not crying out for as long as possible? The waiter!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Waiters&lt;/strong&gt; are the equivalent of &lt;strong&gt;APIs&lt;/strong&gt;. The waiter goes to the customer to get their order, and brings it to them. They will also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prevent overconsumption (in my opinion, two dishes are plenty)&lt;/li&gt;
&lt;li&gt;Offer adaptations if something is unavailable on the menu (we’re out of smoked salmon, but the smoked trout is an excellent alternative)&lt;/li&gt;
&lt;li&gt;Adapt the request timing and arrival in specific cases (let me bring some bread to your kids right now)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the dishes are ready, they’ll also provide the appropriate cutlery for the meals, as well as delivering an overall expected experience. A waiter works very much in a similar way to APIs between your requests (the order off the menu) and the responses (the meals delivered to your table). There are a number of things that happen when you make requests and responses (called policies in API speak), such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Help secure your API calls (sorry, you’ve had enough to drink)&lt;/li&gt;
&lt;li&gt;Apply data transformation (let me cut up the meal for your child) &lt;/li&gt;
&lt;li&gt;Get some more information in order that the backend can do its stuff (do you have any allergies the kitchen should be aware of?) &lt;/li&gt;
&lt;li&gt;Processing a response (you’ve ordered the soup, I’ll bring a spoon)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How do APIs know how to handle these cases? Sure, there are common topics - security, data transformation for example, but how do we deal with specific organization policy? Let’s get back to our restaurant example. There are many common tasks (taking orders and delivering them), but the restaurant may have some specific policies to handle queues, both of customers waiting to get in, and the orders themselves, giving priority to certain orders, or perhaps just having certain ground rules that need to be applied to the restaurant in general. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API Management&lt;/strong&gt; is the equivalent of our &lt;strong&gt;restaurant manager&lt;/strong&gt;, or &lt;strong&gt;Maitre d’&lt;/strong&gt;. The manager will define how the waiters (APIs) will work between the kitchen (backend) and the customers (clients). The manager can also analyze customer flow (monitor global traffic) and how everything is being handled. They will follow up on all the orders, as well as managing how customers are billed for their meal (API monetisation - If you’d like to know more, check out &lt;a href="https://www.gravitee.io/blog/incentivizing-api-providers-and-consumers-through-api-monetization" rel="noopener noreferrer"&gt;this post&lt;/a&gt; by our dear Linus, VP of Product). In addition, API Management can take a more holistic and bigger picture view of what’s going on in the restaurant, and look to make the waiters (APIs) jobs easier. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hire a bouncer at the door to check if patrons are too drunk to be served alcohol (gateway security and/or integrate access management, e.g. Gravitee AM)&lt;/li&gt;
&lt;li&gt;Provide standard policy all waiters follow in relation to hungry children (gateway caching)&lt;/li&gt;
&lt;li&gt;Raise awareness of what’s not currently available on the menu and suggested alternatives ahead of time (gateway dynamic rerouting)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Drawing from our restaurant analogy, in summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restaurant - our system architecture&lt;/li&gt;
&lt;li&gt;Customer - the client application&lt;/li&gt;
&lt;li&gt;Menu - the API definition&lt;/li&gt;
&lt;li&gt;Kitchen - the backend application/service&lt;/li&gt;
&lt;li&gt;Waiter - the API&lt;/li&gt;
&lt;li&gt;Restaurant manager/Maitre d’ - the API Management system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ve covered in this post how i would explain my job to my mom, and I hope if you’re in a similar tech role such as development, architecture, marketing and UX, you’ll appreciate the importance of being able to find a common vocabulary to explain our background, our concepts, our jokes, and ultimately our culture. It is a lot harder to work with each other if we’re not able to share and understand each other. I feel that, as a product owner/manager/team, we’re the bridge (or should I say, the gateway... hmmm hmmm API Management joke) between people.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;In my scrum team, we talk all day long about gateways, proxies, virtual hosts, processors, reactive development, fixing printers (haha, no chance!) and all those weird and wonderful terms. Can you imagine the faces of our User Experience team when we initially explained to them that we need a new user interface for virtual hosting? It goes the same way when you’re helping users - what are they trying to achieve? It matters not that they’ve got an issue with a specific protocol setting (bugs outstanding), what I really want to know is why they're using the product in this way. &lt;/p&gt;

&lt;p&gt;What’s the best way to achieve this outcome? The best advice I've seen so far is to act like a six-year old. Keep asking why. Why? Why? Why? It forces you to really understand what is behind the surface - the 90% of the iceberg, and avoid misunderstanding. Don’t assume that your explanation is simple or straightforward. We all have different backgrounds and you want to make sure they have the same understanding of the concept as you do. If you can explain something to a six-year old, that means you really know your stuff!&lt;/p&gt;

&lt;p&gt;Be a six-year old!&lt;/p&gt;

</description>
      <category>api</category>
      <category>beginners</category>
      <category>apimanagement</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Troubleshoot your APIs with Debug Mode</title>
      <dc:creator>Yann Tavernier</dc:creator>
      <pubDate>Fri, 29 Apr 2022 08:31:06 +0000</pubDate>
      <link>https://dev.to/gravitee/troubleshoot-your-apis-with-debug-mode-47ck</link>
      <guid>https://dev.to/gravitee/troubleshoot-your-apis-with-debug-mode-47ck</guid>
      <description>&lt;p&gt;If you're regularly working with APIs, you'll know the struggles of ensuring that they're secured, protected and managed, as well as building out the core functionality.&lt;/p&gt;

&lt;p&gt;If you haven't already, you'll want to check out API Management. In essence, &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;API management is the process of creating and publishing web application programming interfaces (APIs), enforcing their usage policies, controlling access, nurturing the subscriber community, collecting and analyzing usage statistics, and reporting on performance. API Management components provide mechanisms and tools to support developer and subscriber communities&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(&lt;a href="https://en.wikipedia.org/wiki/API_management" rel="noopener noreferrer"&gt;see on Wikipedia&lt;/a&gt;).&lt;/p&gt;




&lt;p&gt;Using the open source &lt;a href="https://gravitee.io" rel="noopener noreferrer"&gt;Gravitee.io&lt;/a&gt; API Management platform &lt;a href="https://github.com/gravitee-io" rel="noopener noreferrer"&gt;(GitHub repo)&lt;/a&gt; allows you to create, design and manage the lifecycle of your APIs. With many &lt;a href="https://docs.gravitee.io/apim/3.x/apim_policies_overview.html" rel="noopener noreferrer"&gt;rich and powerful policies available&lt;/a&gt;, you have a huge array of tools and techniques to superpower your APIs, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check authentication and manage other security aspects&lt;/li&gt;
&lt;li&gt;Transform headers&lt;/li&gt;
&lt;li&gt;Protocol mediation&lt;/li&gt;
&lt;li&gt;Protect your backends against malicious and accidental traffic spikes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But sometimes, your designs become so complex that it is almost impossible to know where design and configuration problems occur when they pop up. Don’t panic, Debug Mode is here to the rescue. Debug Mode is a feature that unleashes the power of API Publisher, allowing you to design an API, (shadow) deploy it (don’t worry, we’ll explain what shadow deployment is later on), and understand exactly through which policies have been applied to the API call. &lt;/p&gt;

&lt;p&gt;In this blog post, we are going to put ourselves in the shoes of an API publisher, looking at an API displaying some weird behaviors. We will walk through a simple example of an API, and show you not only how to use Debug Mode, but also how it works under the hood.&lt;/p&gt;




&lt;h2&gt;
  
  
  🙋‍♂️ Who am I ?
&lt;/h2&gt;

&lt;p&gt;I am Yann Tavernier and I am a developer in the amazing APIM team. I had the opportunity to work on Debug Mode, and I’m delighted to walk you through and explain this feature!&lt;/p&gt;




&lt;h2&gt;
  
  
  🔑 Key concepts and components
&lt;/h2&gt;

&lt;p&gt;Before we start looking at Debug Mode, let’s provide an overview of all of the key concepts and components that we’ll be using in this blog.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key components:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;APIM is the API Management solution made by Gravitee.io.&lt;/li&gt;
&lt;li&gt;Gateway is the component of APIM responsible for handling requests from customers. As well acting as the proxy for APIs, it will also apply transformation, checks, rate limiting, and so forth on incoming requests and outgoing responses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key concepts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API Publisher is a role type for APIM, representing the user of the company in charge of designing and publishing the APIs.&lt;/li&gt;
&lt;li&gt;API is the representation of your backend inside APIM, and is composed of elements such as documentation, users, design, properties, etc.&lt;/li&gt;
&lt;li&gt;Plan is the access and service layer on top of an API for consumer Applications. Consumer Applications need to subscribe to a plan to be able to consume an API.&lt;/li&gt;
&lt;li&gt;Policy is a service or action that can be executed on an API request or response to perform  checks, transformation or other services to it. As well as out of the box policies, you can also create your own.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎬 Introducing our scenario
&lt;/h2&gt;

&lt;p&gt;We are now going to introduce our simple scenario to walk through how to use Debug Mode.&lt;/p&gt;

&lt;p&gt;All our examples will be done on a local installation. You can use this command to run APIM 3.17 with docker-compose:&lt;br&gt;
&lt;code&gt;cd /tmp &amp;amp;&amp;amp; mkdir -p apim &amp;amp;&amp;amp; cd apim &amp;amp;&amp;amp; curl -L https://raw.githubusercontent.com/gravitee-io/gravitee-docker/master/apim/3.x/docker-compose.yml -o "docker-compose.yml" &amp;amp;&amp;amp; export APIM_VERSION=3.17.1 &amp;amp;&amp;amp; docker-compose down -v &amp;amp;&amp;amp; docker-compose pull &amp;amp;&amp;amp; docker-compose up&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To access the console, go to the following address: &lt;a href="http://localhost:8084" rel="noopener noreferrer"&gt;http://localhost:8084&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The default credentials are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login: admin&lt;/li&gt;
&lt;li&gt;Password: admin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are interested in a more detailed guide, you can check this awesome &lt;a href="https://medium.com/graviteeio/getting-gravitee-io-api-management-platform-up-and-running-on-a-local-machine-9408d07221e6" rel="noopener noreferrer"&gt;blog from Ljubica Lazarevic&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;We will rely on an API called Library backend. You can import it thanks to its API definition &lt;a href="https://raw.githubusercontent.com/gravitee-io/examples/main/troubleshoot-your-APIs/Library-Backend-1.json" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This backend will be accessible on &lt;code&gt;http://localhost:8082/library-backend&lt;/code&gt; and return mocked dataset:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "books": [
       {
           "title": "A tale of two cities",
           "author": "Charles Dickens",
           "_internalReference": "gio_b1"
       },
       {
           "title": "The Lord of the Rings",
           "author": "J.R.R Tolkien",
           "_internalReference": "gio_b2"
       },
       {
           "title": "The Hitchhiker's Guide to the Galaxy",
           "author": "Douglas Adams",
           "_internalReference": "gio_b3"
       }
   ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will analyze this dataset later.&lt;/p&gt;

&lt;p&gt;As an API Publisher, I want to design a “Library” API to access my Library backend. &lt;br&gt;
You can create it following the &lt;a href="https://docs.gravitee.io/apim/3.x/apim_publisherguide_create_apis.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; and follow this guide step by step or you can directly import &lt;a href="https://raw.githubusercontent.com/gravitee-io/examples/main/troubleshoot-your-APIs/Library-1.json" rel="noopener noreferrer"&gt;the resulting API Definition&lt;/a&gt;.&lt;br&gt;
First of all, I need to choose the type of plan to use for my API. We will choose two plans: a Keyless plan, called Free, and an API-Key one, called Premium.&lt;/p&gt;

&lt;p&gt;Let’s firstly design the Free plan. This plan allows anybody to reach our API. To protect our backend systems, as well as improve performance, we want to manage the amount of traffic that will hit our API with this plan. We will limit the access thanks to the Rate Limit policy. One thing to note - as this is a free plan, consuming applications do not need to create a subscription.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyeuv1s4pdel1z8s9bu9n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyeuv1s4pdel1z8s9bu9n.png" alt="Configuring the Rate Limit Policy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the API is going to be publicly accessible, we will want to hide away some private data in the response, the &lt;code&gt;_internalReference&lt;/code&gt; field. To do this, we’re going to use the &lt;a href="https://docs.gravitee.io/apim/3.x/apim_policies_json2json.html" rel="noopener noreferrer"&gt;JSON to JSON Transformation policy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxd0uszjj3anicxiamj76.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxd0uszjj3anicxiamj76.png" alt="Configuring Json to Json Policy on Keyless plan"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the configuration of JsonToJson Policy. Its purpose is to remove the &lt;code&gt;_internalReference&lt;/code&gt; field in the array of &lt;code&gt;books&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    "operation": "remove",
    "spec": {
      "books": {
        "*": {
          "_internalReference": ""
        }
      }
    }
  }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s deploy the API (you can do this by syncing the API when prompted) and call it with a cURL:&lt;br&gt;
Calling &lt;code&gt;curl http://localhost:8082/library&lt;/code&gt; will output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "books": [
       {
           "title": "A tale of two cities",
           "author": "Charles Dickens"
       },
       {
           "title": "The Lord of the Rings",
           "author": "J.R.R Tolkien"
       },
       {
           "title": "The Hitchhiker's Guide to the Galaxy",
           "author": "Douglas Adams"
       }
   ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have successfully hidden away the sensitive, internal data that was being exposed by the API. However, our developer teams may well need access to that data for testing purposes. So what we will do now is create an &lt;strong&gt;Internal&lt;/strong&gt;, API-Key plan, to allow authorized access to the data.It works by verifying the API key that is passed as a header or query parameter, and is linked to an application that has subscribed to the API. You can find out &lt;a href="https://docs.gravitee.io/apim/3.x/apim_publisherguide_plans_subscriptions.html" rel="noopener noreferrer"&gt;more in the documentation&lt;/a&gt; on how to set this up.&lt;/p&gt;

&lt;p&gt;Remember, the &lt;code&gt;_internalReference&lt;/code&gt; removal was done on the Freemium plan. Here, with the Internal plan, we keep the original data. We will use this opportunity to use the &lt;a href="https://docs.gravitee.io/apim/3.x/apim_policies_assign_attributes.html" rel="noopener noreferrer"&gt;Assign Attributes policy&lt;/a&gt; to add an internal attribute in the context. This attribute will be the concatenation of the application’s ID followed by “-internal” and accessible through the “internal” key.&lt;/p&gt;

&lt;p&gt;To do that, we configured the Assign Attribute policy to add an &lt;code&gt;internal&lt;/code&gt; attribute with the following value: &lt;code&gt;{#context.attributes["application"]}-internal&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9bfbvwzla7cr4csbms6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9bfbvwzla7cr4csbms6.png" alt="Configuring Assign Attributes policy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, calling the API with an API Key with &lt;code&gt;curl http://locahost:8082/library?api-key=7cc755d1-378b-4099-9650-9ee9330be55c&lt;/code&gt; will output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "books": [
       {
           "title": "A tale of two cities",
           "author": "Charles Dickens",
           "_internalReference": "gio_b1"
       },
       {
           "title": "The Lord of the Rings",
           "author": "J.R.R Tolkien",
           "_internalReference": "gio_b2"
       },
       {
           "title": "The Hitchhiker's Guide to the Galaxy",
           "author": "Douglas Adams",
           "_internalReference": "gio_b3"
       }
   ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NOTE: You may have noticed that we cannot see the attribute we set. In fact, the attribute only lives inside the API Gateway for the time of the call. This is a behavior of the policy we are using, and it is internal to the gateway.&lt;/p&gt;

&lt;p&gt;Finally, we will create a flow on the API using the JSON to JSON transformation again to apply discounts to a book based on certain conditions. &lt;/p&gt;

&lt;p&gt;The discount will be applied if the response is either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request is done with Header - “X-Library-Discount”:“discount percentage”&lt;/li&gt;
&lt;li&gt;Attribute “internal” is not empty. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default, the discount value will be the value of the X-Library-Discount header, or 10 percent by default.&lt;/p&gt;

&lt;p&gt;To achieve that, we will firstly configure the condition of the policy:&lt;br&gt;
&lt;code&gt;{(#request.headeers['X-Library-Discount'] != null &amp;amp;&amp;amp; #request.headers['X-Library-Discount'].size() &amp;gt; 0) || {#context.attributes['internal'] != null}}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, we will use this configuration for Json to Json Policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
 {
   "operation": "shift",
   "spec": {
     "*": "&amp;amp;"
    }
 },
 {
   "operation": "default",
   "spec": {
     "discount": "{#request.headers['X-Library-Discount'] != null ? #request.headers['X-Library-Discount'][0] : 10}%"
    }
 }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pj358f6bot9neq5e4ob.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pj358f6bot9neq5e4ob.png" alt="Configuring Json to Json Policy at flow level"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Calling the API with &lt;code&gt;curl http://localhost:8082/library?api-key=7cc755d1-378b-4099-9650-9ee9330be55c&lt;/code&gt; will output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "message":"Request failed unintentionally",
    "http_status_code":500
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjwnnjrzdvu6xia9f1ee.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjwnnjrzdvu6xia9f1ee.gif" alt="We are in trouble - Giphy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have some issues with our last flow, but what happened? It’s hard to say by just using cURL or Postman. As the API design complexity increases, the risk of problems also increases. How can we avoid deploying our API to our users until we’ve solved all of the outstanding issues? &lt;/p&gt;

&lt;p&gt;The APIM team created the new Debug Mode to solve this exact challenge.&lt;/p&gt;




&lt;h2&gt;
  
  
  💥 Here comes the Debug Mode!
&lt;/h2&gt;

&lt;p&gt;The Debug Mode feature provides a way to have a global understanding and overview of what happens inside the gateway. With this feature, we are now able to send a request using our HTTP client, and see exactly which policies have been executed, with their inputs and outputs.&lt;/p&gt;

&lt;p&gt;In the following screenshot, you can see an example of a request flow being examined using the Debug Mode:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zrjatnx7i5i34tkf6aq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zrjatnx7i5i34tkf6aq.png" alt="Example of a Debug Mode request"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The request is using the same API key as before, and we can see the Response ended in “500 - Internal Server Error”.&lt;/p&gt;

&lt;p&gt;Let’s take a look at what the Debug Mode feature is showing us. The first important element of this feature is the timeline. It represents each policy that was run, shaped as a card. A card is composed of several elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The name of the policy (e.g. Assign Attributes)&lt;/li&gt;
&lt;li&gt;Its stage (either: platform, security, plan, api) and scope (either: headers, body): Plan &amp;gt; Header&lt;/li&gt;
&lt;li&gt;Its execution time  (e.g. 0.227ms)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ht2mbp7p9uppsk4w6es.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ht2mbp7p9uppsk4w6es.png" alt="A policy card"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It represents the real order of execution of your policies, which may have changed from your initial design. You may notice that the execution could be different from what you expected!&lt;/p&gt;

&lt;p&gt;If you’re a regular user of Gravitee, you are probably used to configuring policies and choosing one of the following scopes: &lt;code&gt;REQUEST&lt;/code&gt;, &lt;code&gt;REQUEST_CONTENT&lt;/code&gt;, &lt;code&gt;RESPONSE&lt;/code&gt;, &lt;code&gt;RESPONSE_CONTENT&lt;/code&gt;. For &lt;code&gt;REQUEST&lt;/code&gt; and &lt;code&gt;RESPONSE&lt;/code&gt; scopes, policy execution has no view or modification access on the content, contrary to &lt;code&gt;REQUEST_CONTENT&lt;/code&gt; and &lt;code&gt;RESPONSE_CONTENT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We will not deep dive into this topic, but an important thing to note is that the gateway will first execute the &lt;strong&gt;header&lt;/strong&gt; policies (&lt;code&gt;REQUEST&lt;/code&gt; / &lt;code&gt;RESPONSE&lt;/code&gt;) and then the &lt;strong&gt;content&lt;/strong&gt; policies (&lt;code&gt;REQUEST_CONTENT&lt;/code&gt; / &lt;code&gt;RESPONSE_CONTENT&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Let’s click on the card to explore what information it provides.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frpbb7pg40j5dwrtom3mc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frpbb7pg40j5dwrtom3mc.png" alt="Debug Mode's differential view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks to this differential view (we will call it a “diff”), we now can see and understand how the Assign Attributes works: it adds an attribute in the Attribute object of the internal context of the call.&lt;/p&gt;

&lt;p&gt;So now, why did our request fail? Let’s scroll the timeline and find the failing policy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0o4y35mrasz7as9tmir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0o4y35mrasz7as9tmir.png" alt="Failing policy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here it is! We can see two icons appearing on our Json to Json Transformation card. Looking at the Inspector, we can see it occurring on Api &amp;gt; Body.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folahtvipqzy49mcjry5p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folahtvipqzy49mcjry5p.png" alt="IF Icon"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IF… means the policy is conditional: it is executed only if the condition is evaluated to true.&lt;/li&gt;
&lt;li&gt;! means the policy has an error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking at the diff, we can see the error message: “Request failed unintentionally”. This is what we saw and caught during the request processing. Unfortunately, in this case, it’s not very helpful.&lt;/p&gt;

&lt;p&gt;The interesting thing, however, is the &lt;strong&gt;Condition&lt;/strong&gt; block:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsa3v0maogy4ze93xi0jk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsa3v0maogy4ze93xi0jk.png" alt="Condition of the failing policy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that the condition is invalid. Reading the condition once more, it looks like we configured our policy using &lt;code&gt;request.headeers&lt;/code&gt; instead of &lt;code&gt;request.headers&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠 How does Debug Mode work ?
&lt;/h2&gt;

&lt;p&gt;So how exactly does Debug Mode work? Let’s take a look under the hood.&lt;/p&gt;

&lt;p&gt;When you send your Debug Request, the API Gateway detects the event, and it starts its processing.&lt;br&gt;
It will deploy your current API in a particular state we call “Shadow Deployment”. This just means that the API is deployed, but not accessible to the public. This deployment is only used by Debug Mode, meaning there is no risk of your customers (or any other users!) accessing this version of your API! &lt;/p&gt;

&lt;p&gt;You don’t need to deploy your API the regular way to be able to debug it. This can be really useful when you are doing some tests to find good tuning for a policy.&lt;/p&gt;

&lt;p&gt;Let’s see it how it works:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkgz4ttfi3yj9aym0xkl8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkgz4ttfi3yj9aym0xkl8.png" alt="Debug Mode Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You send your request to the Debug Mode request form.

&lt;ul&gt;
&lt;li&gt;API Management will then create a Debug Event and store in to the database&lt;/li&gt;
&lt;li&gt;The event’s ID is returned to the user&lt;/li&gt;
&lt;li&gt;Then, the Console UI will poll regularly from APIM REST  API until the event status is  “SUCCESS”.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The Gateway will regularly sync with the database to check if there are some events with the status “TO_DEBUG”&lt;/li&gt;
&lt;li&gt;When an event is found, we deploy our API in shadow mode. 
It implies two things:

&lt;ul&gt;
&lt;li&gt;This API is not accessible for any user, only by the Debug Mode and only for the lifetime of the Debug session.&lt;/li&gt;
&lt;li&gt;This API is built with a particular encapsulation, providing the ability to store the execution information during all the lifecycle of the API.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;An internal HTTP call with the content of the user's debug request is made to this API. It has the advantage of exactly replicating what would happen if you tried to call your API with cURL or Postman.&lt;/li&gt;
&lt;li&gt;The gateway will process your request and transform data based on the configured policies, as usual. The only difference with a regular deployment is that information about headers, payload, context will be stored in the Debug context&lt;/li&gt;
&lt;li&gt;Once the request is finished, the API is undeployed, and debug information is saved to the event.&lt;/li&gt;
&lt;li&gt;Finally, the result is displayed to the user in the Console UI.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  👨‍💻 Back to business
&lt;/h2&gt;

&lt;p&gt;As we said earlier, the condition was misspelled, so we have now fixed &lt;code&gt;request.headeers&lt;/code&gt; to &lt;code&gt;request.headers&lt;/code&gt; in the JSON To JSON policy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffa4w018bzl54l7n03mov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffa4w018bzl54l7n03mov.png" alt="Fixing the condition"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s do the call once again in debug mode:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqtzm5sl7hz7qz8c0fs6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqtzm5sl7hz7qz8c0fs6.png" alt="Debug Mode valid call"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The response is &lt;code&gt;200 - OK&lt;/code&gt;, and we can see the discount applied in the response body.&lt;/p&gt;

&lt;p&gt;Debug Mode can also tell us if a policy is not executing due to an unmet  condition. &lt;br&gt;
If we do not call the API with an api-key or &lt;code&gt;X-Library-Discount&lt;/code&gt;, this JSON to JSON policy will not be applied, as you can see in the timeline:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiz3l61vjxji6e676d5ck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiz3l61vjxji6e676d5ck.png" alt="Skipped policy"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📝 Wrap up
&lt;/h2&gt;

&lt;p&gt;We’ve just done a simple example of a failing API with policy issues, and how to troubleshoot it with Debug Mode. We were able to see and step through the flows to understand what was really happening and what was causing the problem. We have also looked at how exactly Debug Mode works under the hood.&lt;/p&gt;

&lt;p&gt;We would love to hear your feedback, and how you’re getting on with Debug Mode. If the topic interests you and you have questions, do not hesitate to join our &lt;a href="https://community.gravitee.io/" rel="noopener noreferrer"&gt;community forum&lt;/a&gt;. The team will be happy to discuss it with you!&lt;/p&gt;

</description>
      <category>graviteeio</category>
      <category>api</category>
      <category>debug</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
