<?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: Stainless</title>
    <description>The latest articles on DEV Community by Stainless (@stainless).</description>
    <link>https://dev.to/stainless</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%2F10309%2F21e6eb69-3cdf-4882-b32e-18e26009dd82.png</url>
      <title>DEV Community: Stainless</title>
      <link>https://dev.to/stainless</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stainless"/>
    <language>en</language>
    <item>
      <title>MCP for your API</title>
      <dc:creator>Min S Kim</dc:creator>
      <pubDate>Mon, 14 Apr 2025 21:17:35 +0000</pubDate>
      <link>https://dev.to/stainless/mcp-for-your-api-577c</link>
      <guid>https://dev.to/stainless/mcp-for-your-api-577c</guid>
      <description>&lt;p&gt;&lt;a href="https://modelcontextprotocol.io/introduction" rel="noopener noreferrer"&gt;Model Context Protocol (MCP)&lt;/a&gt; is an exciting new way to interact with APIs. Publishing an MCP server helps users interact directly with your API using natural language.&lt;/p&gt;

&lt;p&gt;Our mission is to improve the API layer of the internet, and we’re excited to announce that you can now use Stainless to &lt;a href="https://app.stainless.com/docs/guides/generate-an-mcp-server" rel="noopener noreferrer"&gt;automatically generate MCP servers&lt;/a&gt; (for free) from your OpenAPI spec alongside your SDKs.&lt;/p&gt;

&lt;p&gt;The MCP server generated by Stainless lives alongside your TypeScript SDK and is published as a separate npm package to minimize bundle sizes. It provides composable building blocks to create custom tools, controls to define exactly which parts of the API you want to expose, and an easy way for users to filter which tools they want to use.&lt;/p&gt;

&lt;p&gt;For example, Modern Treasury’s new &lt;a href="https://www.npmjs.com/package/modern-treasury-mcp" rel="noopener noreferrer"&gt;MCP server&lt;/a&gt; enables their customers to do one-off banking operations with simple language:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/UD37BeteYjg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In the demo above, Claude finds an unpaid invoice, voids it, then creates a new one with a different discount using just conversational prompts and the &lt;code&gt;list_invoices&lt;/code&gt;, &lt;code&gt;update_invoice&lt;/code&gt;, and &lt;code&gt;create_invoice tools&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Adding MCP to your Stainless project is simple.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Is5WprkF8lc?start=45"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Navigate to your Stainless project dashboard, click &lt;strong&gt;&lt;code&gt;Add SDKs&lt;/code&gt;&lt;/strong&gt;, then select &lt;strong&gt;&lt;code&gt;MCP Server&lt;/code&gt;&lt;/strong&gt; from the options.&lt;/p&gt;

&lt;p&gt;The generated MCP server can be tested immediately with MCP clients like Claude Desktop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "mcpServers": {
    "your_api": {
      "command": "npx",
      "args": ["-y", "your-api-mcp"],
      "env": {
        "YOUR_API_KEY": "your-api-key-here"
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once configured, you can ask the LLM to interact with your API directly: "What products do we have available?" or "Create a new product called MCP Demo." The LLM will select the appropriate endpoint, pass the necessary parameters, and return the results.&lt;/p&gt;

&lt;p&gt;By default, every endpoint is exposed (e.g., &lt;code&gt;POST /products&lt;/code&gt; would become a &lt;code&gt;create_product tool&lt;/code&gt;). You can fine-tune this by setting &lt;code&gt;enable_all_resources: false&lt;/code&gt; in the &lt;code&gt;mcp_server:&lt;/code&gt; section of your Stainless configuration and adding specific resources or endpoints with &lt;code&gt;mcp: true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Users can also tailor which tools they would like to expose to the model with options like &lt;code&gt;--tool list_accounts&lt;/code&gt;, &lt;code&gt;--resource accounts&lt;/code&gt;, or &lt;code&gt;--operation read&lt;/code&gt; to reduce context size or prevent access to sensitive data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying remote MCP servers to Cloudflare Workers
&lt;/h2&gt;

&lt;p&gt;The examples above are great for devs using local AI clients. But for non-devs using web apps, local MCP servers that rely on API keys for auth aren’t practical.&lt;/p&gt;

&lt;p&gt;This is where remote MCP servers come in. It’s a newer part of the Model Context Protocol spec that enables OAuth-based authentication between clients and servers. While support is &lt;a href="https://modelcontextprotocol.io/development/roadmap#registry" rel="noopener noreferrer"&gt;still nascent&lt;/a&gt;, you can use this today by deploying your Stainless-generated tools to a Cloudflare Worker.&lt;/p&gt;

&lt;p&gt;The worker can handle OAuth with your existing provider or you can implement a custom flow directly in the worker. Check out the &lt;a href="https://app.stainless.com/docs/guides/generate-an-mcp-server#deploy-a-remote-mcp-server" rel="noopener noreferrer"&gt;docs&lt;/a&gt; for more info.&lt;/p&gt;




&lt;p&gt;MCP server generation is currently experimental and is free to all Stainless users.&lt;/p&gt;

&lt;p&gt;Get started today at &lt;a href="http://app.stainless.com/login" rel="noopener noreferrer"&gt;stainless.com/login&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Making Java enums forwards compatible</title>
      <dc:creator>Tomer Aberbach</dc:creator>
      <pubDate>Tue, 11 Feb 2025 19:57:13 +0000</pubDate>
      <link>https://dev.to/stainless/making-java-enums-forwards-compatible-1cmm</link>
      <guid>https://dev.to/stainless/making-java-enums-forwards-compatible-1cmm</guid>
      <description>&lt;p&gt;SDKs, like most downloaded software, quickly end up with client-server &lt;a href="https://www.industrialempathy.com/posts/version-skew/" rel="noopener noreferrer"&gt;version skew&lt;/a&gt;. A great SDK gracefully handles skew by being forwards compatible with potential API changes.&lt;/p&gt;

&lt;p&gt;This is especially important for Java SDKs, which could to be used in Android apps that users take a long time to update (if they update at all). An app shouldn’t start crashing just because it’s not using the latest SDK version!&lt;/p&gt;

&lt;p&gt;It turns out Java enums are not trivially forwards compatible in this way.&lt;/p&gt;

&lt;h2&gt;
  
  
  An example API
&lt;/h2&gt;

&lt;p&gt;Suppose we’re designing a Java SDK for a Pet Store API. We might end up with an enum for representing order status:&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;enum&lt;/span&gt; &lt;span class="nc"&gt;PetOrderStatus&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;PLACED&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;APPROVED&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;DELIVERED&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;Users of our SDK would find this type more convenient than a &lt;code&gt;String&lt;/code&gt; because it indicates exactly which statuses are possible. Users can even use &lt;a href="https://docs.oracle.com/en/java/javase/17/language/switch-expressions-and-statements.html" rel="noopener noreferrer"&gt;“switch expressions”&lt;/a&gt; to ensure they handle all possible statuses:&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;String&lt;/span&gt; &lt;span class="n"&gt;displayText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;petOrderStatus&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;PLACED&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Your order was placed and is being reviewed."&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;APPROVED&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Your order was approved."&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;DELIVERED&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Your order was delivered!"&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;But how do we convert a string from the API response into an enum constant?&lt;/p&gt;

&lt;p&gt;The most common way to parse a string into an enum constant is using the built-in &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html#valueOf-java.lang.Class-java.lang.String-" rel="noopener noreferrer"&gt;&lt;code&gt;Enum.valueOf&lt;/code&gt;&lt;/a&gt; method, which is automatically generated for every enum:&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;PetOrderStatus&lt;/span&gt; &lt;span class="n"&gt;petOrderStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nc"&gt;PetOrderStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statusString&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toUpperCase&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works, but there are problems lurking.&lt;/p&gt;

&lt;h2&gt;
  
  
  An API change
&lt;/h2&gt;

&lt;p&gt;Suppose one day our product manager pings us and says, “Customers want to know when their fluffball is on the way. Is that possible?”&lt;/p&gt;

&lt;p&gt;“Sounds reasonable,” we think to ourselves. So we implement the feature, add &lt;code&gt;"in_transit"&lt;/code&gt; as a possible order status in the API, and update our SDK and app like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; enum PetOrderStatus {
     PLACED,
     APPROVED,
&lt;span class="gi"&gt;+    IN_TRANSIT,
&lt;/span&gt;     DELIVERED,
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; String displayText = switch (petOrderStatus) {
     case PLACED -&amp;gt; "Your order was placed and is being reviewed.";
     case APPROVED -&amp;gt; "Your order was approved.";
&lt;span class="gi"&gt;+    case IN_TRANSIT -&amp;gt; "Your order is on the way!";
&lt;/span&gt;     case DELIVERED -&amp;gt; "Your order was delivered!";
 };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The feature works fine in our local environment so we decide to ship the changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crashes galore
&lt;/h2&gt;

&lt;p&gt;Almost immediately, we start getting crash reports for the Pet Store app. They all look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;Exception in thread "main" java.lang.IllegalArgumentException: No enum constant PetOrderStatus.IN_TRANSIT
&lt;/span&gt;    at java.base/java.lang.Enum.valueOf(Enum.java)
    at PetOrderStatus.valueOf(PetStoreApp.java)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we &lt;em&gt;did&lt;/em&gt; update the SDK enum with an &lt;code&gt;IN_TRANSIT&lt;/code&gt; constant! What gives?&lt;/p&gt;

&lt;p&gt;It turns out that all of the crashes are coming from customers who haven’t updated their app yet. In that previous version, &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html#valueOf-java.lang.Class-java.lang.String-" rel="noopener noreferrer"&gt;&lt;code&gt;Enum.valueOf&lt;/code&gt;&lt;/a&gt; throws an &lt;code&gt;IllegalArgumentException&lt;/code&gt; when the input doesn’t match any known enum constant.&lt;/p&gt;

&lt;p&gt;The API started including &lt;code&gt;"in_transit"&lt;/code&gt; in responses, but almost all customers are still using the previous SDK version!&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;So what’s an SDK engineer to do? How could we have avoided this incident?&lt;/p&gt;

&lt;p&gt;One option is to make the type &lt;code&gt;Optional&amp;lt;PetOrderStatus&amp;gt;&lt;/code&gt; instead of just &lt;code&gt;PetOrderStatus&lt;/code&gt;, which would allow us to return &lt;code&gt;Optional.empty()&lt;/code&gt; when the value is not a known constant. This isn’t ideal for a few reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can’t access the raw API value in the &lt;code&gt;Optional.empty()&lt;/code&gt; case.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Optional.empty()&lt;/code&gt; looks like it means there’s no order status, but that’s not what we’re trying to convey.&lt;/li&gt;
&lt;li&gt;What if we want to represent the concept of “no order status” in the future? We would no longer be able to use &lt;code&gt;Optional.empty()&lt;/code&gt; for that!&lt;sup id="fnref1"&gt;1&lt;/sup&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A more robust solution would be to store the raw API value and provide access to both the raw value &lt;em&gt;and&lt;/em&gt; an enum representation of it.&lt;/p&gt;

&lt;p&gt;We might end up with a class that 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;public&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PetOrderStatus&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;PetOrderStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/** Used to "parse" the API value. */&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;PetOrderStatus&lt;/span&gt; &lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;value&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PetOrderStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/** Returns the raw API value. */&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;_value&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;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/** Returns an enum containing known order statuses. */&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Value&lt;/span&gt; &lt;span class="nf"&gt;value&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="nf"&gt;switch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"placed"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PLACED&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"approved"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;APPROVED&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"delivered"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DELIVERED&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;_UNKNOWN&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Value&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;PLACED&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;APPROVED&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;DELIVERED&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="cm"&gt;/** The order status is not known to this SDK version. */&lt;/span&gt;
        &lt;span class="n"&gt;_UNKNOWN&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;And our SDK users could use the class like so:&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;String&lt;/span&gt; &lt;span class="n"&gt;displayText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;petOrderStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;PLACED&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Your order was placed and is being reviewed."&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;APPROVED&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Your order was approved."&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;DELIVERED&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Your order was delivered!"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Fallback for new order statuses not known to this SDK version.&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;_UNKNOWN&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Your order status is: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;petOrderStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;_value&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;This design has several benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We still get all the benefits of enums, including exhaustiveness checks that now require us to handle the unknown status case.&lt;/li&gt;
&lt;li&gt;We can still use the raw API value in the unknown status case.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  An API change: part 2
&lt;/h2&gt;

&lt;p&gt;With this new SDK design, our app wouldn’t have started crashing after the API change. Instead, previous app versions would have displayed the following message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your order status is: in_transit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if we had made the following change to our SDK and app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; public final class PetOrderStatus {
     // ...
&lt;span class="err"&gt;
&lt;/span&gt;     public Value value() {
         return switch (value) {
             case "placed" -&amp;gt; Value.PLACED;
             case "approved" -&amp;gt; Value.APPROVED;
&lt;span class="gi"&gt;+            case "in_transit" -&amp;gt; Value.IN_TRANSIT; 
&lt;/span&gt;             case "delivered" -&amp;gt; Value.DELIVERED;
             default -&amp;gt; Value._UNKNOWN;
         };
     }
&lt;span class="err"&gt;
&lt;/span&gt;     public enum Value {
         PLACED,
         APPROVED,
&lt;span class="gi"&gt;+        IN_TRANSIT,
&lt;/span&gt;         DELIVERED,
         /** The order status is not known to this SDK version. */
         _UNKNOWN,
     }
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; String displayText = switch (petOrderStatus.value()) {
     case PLACED -&amp;gt; "Your order was placed and is being reviewed.";
     case APPROVED -&amp;gt; "Your order was approved.";
&lt;span class="gi"&gt;+    case IN_TRANSIT -&amp;gt; "Your order is on the way!";
&lt;/span&gt;     case DELIVERED -&amp;gt; "Your order was delivered!";
     // Fallback for new order statuses not known to this SDK version.
     case _UNKNOWN -&amp;gt; "Your order status is: " + petOrderStatus._value();
 };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then customers would get better display text the next time they update.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.stainlessapi.com/signup" rel="noopener noreferrer"&gt;Try Stainless today&lt;/a&gt;.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Yes, we could do &lt;code&gt;Optional&amp;lt;Optional&amp;lt;PetOrderStatus&amp;gt;&amp;gt;&lt;/code&gt;, but good luck getting that through design review. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>java</category>
      <category>api</category>
    </item>
  </channel>
</rss>
