<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Sakalya Deshpande on Medium]]></title>
        <description><![CDATA[Stories by Sakalya Deshpande on Medium]]></description>
        <link>https://medium.com/@deshpande.sakalya?source=rss-fd0cb32fa144------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*41BsZqGho1ReNseoJVOwQA.jpeg</url>
            <title>Stories by Sakalya Deshpande on Medium</title>
            <link>https://medium.com/@deshpande.sakalya?source=rss-fd0cb32fa144------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 23 May 2026 15:49:32 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@deshpande.sakalya/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Overload Control Strategies in Microservices]]></title>
            <link>https://medium.com/@deshpande.sakalya/overload-control-strategies-in-microservices-605b53284cb4?source=rss-fd0cb32fa144------2</link>
            <guid isPermaLink="false">https://medium.com/p/605b53284cb4</guid>
            <category><![CDATA[microservices]]></category>
            <category><![CDATA[algorithms]]></category>
            <category><![CDATA[system-design-interview]]></category>
            <category><![CDATA[distributed-systems]]></category>
            <dc:creator><![CDATA[Sakalya Deshpande]]></dc:creator>
            <pubDate>Mon, 01 May 2023 07:45:03 GMT</pubDate>
            <atom:updated>2023-05-01T07:45:03.897Z</atom:updated>
            <content:encoded><![CDATA[<p>In microservices, overload control refers to the process of managing traffic levels within a network to ensure that service instances do not become overloaded or fail due to excessive traffic demands. This is accomplished by implementing mechanisms that enable traffic to be intelligently distributed across service instances based on factors such as load, health, and performance.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1002/1*VfdXjc9PPkb9_LcpONRwTw.png" /></figure><p>Overload control is important in service meshes because they often handle large volumes of traffic across multiple microservices. Without proper overload control mechanisms, a sudden surge in traffic to a particular service could cause it to become overwhelmed and fail, leading to service disruptions and degraded performance for end-users.</p><p>Some common mechanisms for overload control in service meshes include:</p><ol><li>Circuit breaking: A technique that prevents requests from being sent to an overloaded service by detecting and tripping open the circuit when the service is unable to handle the load.</li><li>Rate limiting: A mechanism that limits the rate at which requests can be sent to a service, preventing it from being overwhelmed with too many requests.</li><li>Load shedding: A technique that reduces the amount of traffic directed to a service during periods of high load, prioritising more critical requests over less critical ones.</li></ol><p>A very few Service Mesh technologies provide intelligent way of handling overload.</p><p>Following is the way proposed by WeChat in their paper which handles overload gracefully.</p><p><strong>Business-oriented Admission Control</strong></p><p>The idea behind business-oriented admission control is to prioritise service requests based on their importance to the overall business and user experience. For example, requests related to user authentication and payment processing may be given higher priority than requests related to messaging or content delivery.</p><p>This approach recognises that different services may have different levels of importance and impact on the user experience, and that overload control strategies should take this into account when managing traffic and allocating resources. By prioritising requests based on their business significance, the system can ensure that the most critical services and requests are handled first, even during periods of high load or resource constraints.</p><p><strong>User-oriented Admission Control</strong></p><p>This technique considers the priority of requests not only based on their business impact but also on the specific user making the request. For example, a request from a high-value user may be given a higher priority than the same request from a low-value user.</p><p>With user-oriented admission control, when the service is overloaded, requests with the same business priority are not necessarily all discarded or all consumed. Instead, the admission decision for each request is based on both its business priority and the user making the request. This approach can help to better balance the workload among different users and prevent the issue of partially discarding requests.</p><p>Adaptive admission control is a dynamic approach to load shedding in microservices that adjusts admission levels in response to changes in load status. This approach is particularly effective when services are overloaded, as the corresponding load shedding strategy is dependent on the volume of excess workload. The goal of adaptive admission control is to minimize the impact of load shedding on the quality of service while maintaining effective load shedding.</p><p><strong>Adaptive Admission Control</strong></p><p>In an adaptive admission control system, admission levels are automatically adjusted in response to changes in load status. When the overload situation is severe, admission levels are restricted to reject more incoming requests. Conversely, when the overload situation becomes mild, admission levels are relaxed. This allows for effective load shedding while minimizing the impact on the overall service.</p><p>Adaptive admission control is particularly important in complex microservice architectures, where the adjustment of admission levels of overloaded services must be automatic and adaptive. The DAGOR overload control system relies on adaptive admission control to maintain the performance of the microservice system during periods of high load.</p><p>Here is a step-by-step workflow for overload control based on above strategies:</p><ol><li>User request arrives at the microservice system and is routed to the entry service.</li><li>Entry service assigns business and user priorities to the request and encapsulates these priorities into the request header.</li><li>Each service invokes downstream services according to the business logic.</li><li>When a service receives a request, it performs priority-based admission control based on its current admission level. The service periodically adjusts its admission level with respect to the load status.</li><li>When a service intends to send a subsequent request to a downstream service, it performs local admission control based on the stored admission level of the downstream service. The upstream service only sends out requests that are admitted by the local admission control.</li><li>When a downstream service sends a response to an upstream service, it piggybacks its current admission level to the response message.</li><li>When the upstream service receives the response, it extracts the information of admission level from the message and updates the corresponding local record for the downstream service accordingly.</li><li>If a service becomes overloaded, it adjusts its admission level to restrict more incoming requests. Conversely, when the overload situation becomes mild, the admission levels should be relaxed.</li><li>Requests with the same business priority may be partially discarded if necessary due to fluctuation in admission levels.</li><li>The adaptive admission control system ensures that admission levels are automatically and adaptively adjusted in response to changes in load status.</li></ol><p>Happy Learning !!!!!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=605b53284cb4" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What is a Monorepo ?]]></title>
            <link>https://medium.com/@deshpande.sakalya/what-is-a-monorepo-db434da94e5d?source=rss-fd0cb32fa144------2</link>
            <guid isPermaLink="false">https://medium.com/p/db434da94e5d</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[sdlc]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[distributed-systems]]></category>
            <dc:creator><![CDATA[Sakalya Deshpande]]></dc:creator>
            <pubDate>Sun, 09 Apr 2023 07:57:29 GMT</pubDate>
            <atom:updated>2023-04-09T08:10:29.037Z</atom:updated>
            <content:encoded><![CDATA[<h3>What is a Monorepo ?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/638/1*Ox_gK7auirKrlZXLwdvKEQ.jpeg" /></figure><p>Microservices architectural pattern dominates the modern software development . It definitely has its own set of advantages.</p><p>In the context of microservices architecture, “polyrepo” refers to the practice of using multiple separate version control repositories for each individual microservice.</p><p>While using a polyrepo approach in microservices development can offer some benefits, such as loose coupling and independent release cycles for individual microservices, it also has potential disadvantages, which may include:</p><p><strong>Complexity in managing dependencies</strong>: With each microservice having its own repository, managing dependencies among microservices can become more challenging. Changes in one microservice may require updates in multiple other microservices, leading to increased coordination efforts and potential versioning conflicts.</p><p><strong>Overhead in managing multiple repositories</strong>: Managing multiple repositories may require additional tooling, processes, and overhead for tasks such as branching, merging, and managing release versions. It can also result in increased administrative overhead, such as managing access controls and permissions for multiple repositories.</p><p><strong>Code duplication and inconsistency</strong>: Microservices are often designed to be highly decoupled and independent, but there may still be shared code, libraries, or configurations among microservices. With a polyrepo approach, there may be a risk of code duplication or inconsistency, as each microservice may independently implement and maintain similar functionality.</p><p><strong>Lack of cross-repo visibility and traceability</strong>: In a polyrepo approach, it may be more difficult to have a unified view of the entire system and track changes across microservices. This can make it challenging to trace and understand the impact of changes on the system as a whole, and can hinder visibility into the overall system’s state.</p><p><strong>Potential overhead in build and deployment processes</strong>: Managing the build, testing, and deployment processes across multiple repositories may require additional effort and tooling, as compared to a monorepo approach where all the code is stored in a single repository. This can increase the complexity and time required for managing the build and release processes.</p><p>Monorepo tries to solve these problems by storing all the source code for multiple projects or applications in a single version control repository.There are a couple of tools to use monorepo practise in software development. Google’s Bazel and Meta’s Buck are popular among all of these.</p><p>Here’s an example of how you could set up a <strong>monorepo using Bazel for an e-commerce application with a Python web server for the order system and a Golang server for the payment system</strong>:</p><p><strong>Directory Structure</strong>: Create a root directory for your monorepo, and inside it, create directories for your backend components, including the order system and payment system.</p><pre>e-commerce-monorepo/<br>  ├── order/<br>  │   ├── BUILD<br>  │   ├── src/<br>  │   └── ...<br>  ├── payment/<br>  │   ├── BUILD<br>  │   ├── src/<br>  │   └── ...<br>  └── ... </pre><p><strong>Order System</strong> — Python Web Server: In the order directory, you can have your Python web server application for the order system. You can use a framework like Flask or Django to build your web server. Create a BUILD file in the order directory that describes how to build the order system using Bazel. Here&#39;s an example BUILD file for a hypothetical Flask-based order system:</p><pre>py_binary(<br>    name = &quot;order_server&quot;,<br>    srcs = glob([&quot;src/*.py&quot;]),<br>    deps = [],  # Define dependencies as needed<br>)</pre><p><strong>Payment System</strong> — Golang Server: In the payment directory, you can have your Golang server application for the payment system. You can use a framework like Gin or Revel to build your server. Create a BUILD file in the payment directory that describes how to build the payment system using Bazel. Here&#39;s an example BUILD file for a hypothetical Gin-based payment system:</p><pre>go_binary(<br>    name = &quot;payment_server&quot;,<br>    srcs = glob([&quot;src/*.go&quot;]),<br>    deps = [],  # Define dependencies as needed<br>)</pre><p><strong>Build Targets</strong>: To build the order system or payment system targets, you can use the bazel build command, followed by the label of the target you want to build. For example:</p><pre>bazel build //order:order_server<br><br>bazel build //payment:payment_server</pre><p>Bazel will automatically determine the correct build order based on the dependencies defined in the BUILD files and build the targets accordingly.</p><p>Happy Learning !!!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=db434da94e5d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Things I Wish I Knew Before Using Apache Cassandra]]></title>
            <link>https://medium.com/stuff-technology/things-i-wish-i-knew-before-using-apache-cassandra-3ccdd2707ac5?source=rss-fd0cb32fa144------2</link>
            <guid isPermaLink="false">https://medium.com/p/3ccdd2707ac5</guid>
            <dc:creator><![CDATA[Sakalya Deshpande]]></dc:creator>
            <pubDate>Tue, 28 Apr 2020 10:14:29 GMT</pubDate>
            <atom:updated>2020-04-28T10:31:23.758Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZTYfFC_H2LtHZUr8F8Nihw.jpeg" /><figcaption>Apache Cassandra Logo</figcaption></figure><p><strong>Apache Cassandra</strong> is a highly scalable, high-performance distributed database designed to handle large amounts of data across many commodity servers, providing high availability with no single point of failure. It is a type of NoSQL database.</p><p>Though Apache Cassandra has many good features that make it a highly scalable and high-performance database, this scalability and performance come with a cost. Sometimes this cost is too high to afford for a business.</p><p>Hence, I would like you to know some of the things about Apache Cassandra before using it in Production.</p><h3><strong>Deleting bulk data from Cassandra table makes reads very slow</strong></h3><p>In Cassandra, when you delete a record, it does not hard delete it and just creates a tombstone.</p><p>In the context of Cassandra, a tombstone is specific data stored alongside standard data. A delete operation does nothing more than inserting a tombstone. And when you read data from this table, Cassandra has to scan all non-deleted/live records plus tombstones making the reads slower. There is a configuration(gc_grace_seconds) per table after that tombstones get deleted. Also if your tombstones limit reaches a threshold value, you cannot read from your table. All reads are stopped till you get tombstones cleared on every Cassandra Node in the cluster.</p><h3><strong>If you model your tables incorrectly, your application is screwed</strong></h3><p>When designing a table in Cassandra, you have to specify <strong>Partition Key</strong> and <strong>Clustering Key.</strong> The partition key allows the database to quickly retrieve the data from the appropriate node. The database requires that all partition keys are restricted or none. All the partition key columns are required to compute the hash and locate the node containing the partition. If you want to fetch data from multiple partitions, brace yourself for ReadTimeoutExceptions.</p><h3><strong>Choose one of the two “strong consistency” or “high availability”</strong></h3><p>This should hold true for all distributed databases and not just Cassandra. But you have to choose one of these properties carefully, else either your application will not be available for some time or it will be available but return stale data.</p><h3><strong>Having too many tables in a cluster cause performance degradation</strong></h3><p>According to Datastax documentation, Once your database reaches the warning threshold(200 tables), it’s time to start monitoring and planning a re-architecture. If possible, remove unused and underutilized tables. The failure threshold is 500 tables.</p><h3><strong>SELECT….IN query — A big NO!!!!!!!!!!!!!!!!!!!!!!!!!</strong></h3><p>Under most conditions, using IN in relation to the partition key is not recommended. To process a list of values, the SELECT may have to query many nodes, which degrades performance and may cause timeouts.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3ccdd2707ac5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/stuff-technology/things-i-wish-i-knew-before-using-apache-cassandra-3ccdd2707ac5">Things I Wish I Knew Before Using Apache Cassandra</a> was originally published in <a href="https://medium.com/stuff-technology">STUFF.TECHNOLOGY</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why HTTP GET is not a good idea sometimes]]></title>
            <link>https://medium.com/@deshpande.sakalya/why-http-get-is-not-a-good-idea-sometimes-3e52ff15c42d?source=rss-fd0cb32fa144------2</link>
            <guid isPermaLink="false">https://medium.com/p/3e52ff15c42d</guid>
            <category><![CDATA[api-development]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[api-design]]></category>
            <category><![CDATA[rest-api]]></category>
            <category><![CDATA[api-integration]]></category>
            <dc:creator><![CDATA[Sakalya Deshpande]]></dc:creator>
            <pubDate>Fri, 14 Jun 2019 06:40:29 GMT</pubDate>
            <atom:updated>2019-06-14T06:40:29.199Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/658/1*VnRw2Us7oIWHoVOI3I8xjw.png" /></figure><p>Recently, I started observing RequestTooLarge Exceptions in our API. After careful analysis, I got to know that there is a limit on the length of URL decided by most of the REST clients as well as servers. Though this limit is not standardized by HTTP specification, we have to respect this limit as we are dependent on standard REST clients and web servers to host and to call our API. The practical range of this limit is between 2Kb to 8Kb.</p><p>But wait, this is not the only limitation that GET has. It also have following limitations</p><ol><li>URL Encoding is required before calling a GET API else be ready for some surprises in your API results. This encoding is required because your client can not encode the special characters like space, ampersand, brackets and what not automatically.</li><li>It is difficult to perform complex queries as URLs are not expressive as JSON or XML.</li></ol><p>Now you may say , enough badmouthing about HTTP GET, tell us how we can solve these limitations ?</p><p>A very standard way of solving these limitations is using POST instead of GET. But POST is a way to create a resource while GET is for retrieving, how can I use it ? The answer is treat your “search” as a resource.</p><p>For Example,</p><p>Instead of GET /reports?filter=filter1&amp;startDate=date1&amp;endDate=date2 ,</p><p>Use POST /reports/search and give filter, startDate and endDate as request body. (Now, I know why ElasticSearch uses this format).</p><p>I understand that this may not be the exactly compliant with HTTP standards.And this may lead to some other problems like for POST, client will not cache request similar to GET, and POST being non-idempotent, client may assume that retrying same request may be harmful.</p><p>Hence, I would advise this should be used if your API are for reporting, heavy searches. Also, some companies are exploring HTTP’s new verb REPORT ( <a href="http://www.iana.org/assignments/http-methods/http-methods.xhtml">http://www.iana.org/assignments/http-methods/http-methods.xhtml</a>) which solves problems of both GET and POST and fits this use case.</p><p>Happy API Designing !!!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3e52ff15c42d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How To Enable HTTPS In Spring Boot Application]]></title>
            <link>https://medium.com/stuff-technology/how-to-enable-https-in-spring-boot-application-68fb03243852?source=rss-fd0cb32fa144------2</link>
            <guid isPermaLink="false">https://medium.com/p/68fb03243852</guid>
            <category><![CDATA[spring-boot]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[https]]></category>
            <category><![CDATA[java]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Sakalya Deshpande]]></dc:creator>
            <pubDate>Tue, 01 Jan 2019 09:47:26 GMT</pubDate>
            <atom:updated>2019-01-01T09:47:26.017Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NlqpTTAM8DbGl4paBmjE_g.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/m_HRfLhgABo?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Christopher Gower</a> on <a href="https://unsplash.com/search/photos/coding?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Spring Boot provides a configurable and programmatic way to enable HTTPS on your web application. In this article, we will see each of these ways in detail.</p><h3><strong>Enable HTTPS using Configuration</strong></h3><ol><li>You need to create a self-signed SSL certificate. The two most common formats used for keystores are JKS, specific for Java, and PKCS12, an industry standard format. JKS used to be the default choice, but now Oracle recommends to adopt the PKCS12 format. We will use PKCS12 format in the example.</li><li>Open your command prompt and enter the following command.</li></ol><pre>keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650</pre><p>3. As an output of this command, you will be asked to enter the password for your keystore.</p><p>4. Once your password is accepted, you will be asked some information to enter like first name, last name, city, country but you can skip those.</p><p>5. Once you have entered all the required information, a keystore will be created. verify that using the following command</p><pre>keytool -list -v -storetype pkcs12 -keystore keystore.p12</pre><p>6. Now we have SSL Certificate ready, the only thing that is remaining is changing your application.properties/application.yml in your Spring Boot application.</p><pre>server.port=50125 <br>security.require-ssl=true <br>server.ssl.key-store-type=PKCS12 <br>server.ssl.key-store=classpath:keystore.p12 <br>server.ssl.key-store-password=password<br>server.ssl.key-alias=tomcat</pre><h3>Enable HTTPS Programmatically</h3><ol><li>Declare @Configuration class e.g. TomcatConfig.java in which you need to create an instance of the class org.apache.catalina.connector.Connector and set SSL(org.springframework.boot.web.server.Ssl) information to the instance of this Connector.</li><li>Create another class SslConnectorCustomizer which actually configures SSL using Tomcat’s API.</li></ol><pre>package com.demo.https;</pre><pre>import java.io.FileNotFoundException;</pre><pre>import org.apache.catalina.connector.Connector;<br>import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory;<br>import org.apache.coyote.ProtocolHandler;<br>import org.apache.coyote.http11.AbstractHttp11JsseProtocol;<br>import org.apache.coyote.http11.Http11NioProtocol;<br>import org.apache.tomcat.util.net.SSLHostConfig;</pre><pre>import org.springframework.boot.web.server.Ssl;<br>import org.springframework.boot.web.server.SslStoreProvider;<br>import org.springframework.boot.web.server.WebServerException;<br>import org.springframework.util.Assert;<br>import org.springframework.util.ResourceUtils;<br>import org.springframework.util.StringUtils;</pre><pre>class SslConnectorCustomizer {</pre><pre>private final Ssl ssl;</pre><pre>private final SslStoreProvider sslStoreProvider;</pre><pre>SslConnectorCustomizer(Ssl ssl, SslStoreProvider sslStoreProvider) {<br>        Assert.notNull(ssl, &quot;Ssl configuration should not be null&quot;);<br>        this.ssl = ssl;<br>        this.sslStoreProvider = sslStoreProvider;<br>    }</pre><pre>public void customize(Connector connector) {<br>        ProtocolHandler handler = connector.getProtocolHandler();<br>        Assert.state(handler instanceof AbstractHttp11JsseProtocol,<br>                &quot;To use SSL, the connector&#39;s protocol handler must be an &quot;<br>                        + &quot;AbstractHttp11JsseProtocol subclass&quot;);<br>        configureSsl((AbstractHttp11JsseProtocol&lt;?&gt;) handler, this.ssl,<br>                this.sslStoreProvider);<br>        connector.setScheme(&quot;https&quot;);<br>        connector.setSecure(true);<br>    }</pre><pre>    protected void configureSsl(AbstractHttp11JsseProtocol&lt;?&gt; protocol, Ssl ssl,<br>                                SslStoreProvider sslStoreProvider) {<br>        protocol.setSSLEnabled(true);<br>        protocol.setSslProtocol(ssl.getProtocol());<br>        configureSslClientAuth(protocol, ssl);<br>        protocol.setKeystorePass(ssl.getKeyStorePassword());<br>        protocol.setKeyPass(ssl.getKeyPassword());<br>        protocol.setKeyAlias(ssl.getKeyAlias());<br>        String ciphers = StringUtils.arrayToCommaDelimitedString(ssl.getCiphers());<br>        if (StringUtils.hasText(ciphers)) {<br>            protocol.setCiphers(ciphers);<br>        }<br>        if (ssl.getEnabledProtocols() != null) {<br>            for (SSLHostConfig sslHostConfig : protocol.findSslHostConfigs()) {<br>                sslHostConfig.setProtocols(StringUtils<br>                        .arrayToCommaDelimitedString(ssl.getEnabledProtocols()));<br>            }<br>        }<br>        if (sslStoreProvider != null) {<br>            configureSslStoreProvider(protocol, sslStoreProvider);<br>        }<br>        else {<br>            configureSslKeyStore(protocol, ssl);<br>            configureSslTrustStore(protocol, ssl);<br>        }<br>    }</pre><pre>private void configureSslClientAuth(AbstractHttp11JsseProtocol&lt;?&gt; protocol, Ssl ssl) {<br>        if (ssl.getClientAuth() == Ssl.ClientAuth.NEED) {<br>            protocol.setClientAuth(Boolean.TRUE.toString());<br>        }<br>        else if (ssl.getClientAuth() == Ssl.ClientAuth.WANT) {<br>            protocol.setClientAuth(&quot;want&quot;);<br>        }<br>    }</pre><pre>protected void configureSslStoreProvider(AbstractHttp11JsseProtocol&lt;?&gt; protocol,<br>                                             SslStoreProvider sslStoreProvider) {<br>        Assert.isInstanceOf(Http11NioProtocol.class, protocol,<br>                &quot;SslStoreProvider can only be used with Http11NioProtocol&quot;);<br>        TomcatURLStreamHandlerFactory instance = TomcatURLStreamHandlerFactory<br>                .getInstance();<br>        instance.addUserFactory(<br>                new SslStoreProviderUrlStreamHandlerFactory(sslStoreProvider));<br>        try {<br>            if (sslStoreProvider.getKeyStore() != null) {<br>                protocol.setKeystorePass(&quot;&quot;);<br>                protocol.setKeystoreFile(<br>                        SslStoreProviderUrlStreamHandlerFactory.KEY_STORE_URL);<br>            }<br>            if (sslStoreProvider.getTrustStore() != null) {<br>                protocol.setTruststorePass(&quot;&quot;);<br>                protocol.setTruststoreFile(<br>                        SslStoreProviderUrlStreamHandlerFactory.TRUST_STORE_URL);<br>            }<br>        }<br>        catch (Exception ex) {<br>            throw new WebServerException(&quot;Could not load store: &quot; + ex.getMessage(), ex);<br>        }<br>    }</pre><pre>private void configureSslKeyStore(AbstractHttp11JsseProtocol&lt;?&gt; protocol, Ssl ssl) {<br>        try {<br>            protocol.setKeystoreFile(ResourceUtils.getURL(ssl.getKeyStore()).toString());<br>        }<br>        catch (FileNotFoundException ex) {<br>            throw new WebServerException(&quot;Could not load key store: &quot; + ex.getMessage(),<br>                    ex);<br>        }<br>        if (ssl.getKeyStoreType() != null) {<br>            protocol.setKeystoreType(ssl.getKeyStoreType());<br>        }<br>        if (ssl.getKeyStoreProvider() != null) {<br>            protocol.setKeystoreProvider(ssl.getKeyStoreProvider());<br>        }<br>    }</pre><pre>private void configureSslTrustStore(AbstractHttp11JsseProtocol&lt;?&gt; protocol, Ssl ssl) {<br>        if (ssl.getTrustStore() != null) {<br>            try {<br>                protocol.setTruststoreFile(<br>                        ResourceUtils.getURL(ssl.getTrustStore()).toString());<br>            }<br>            catch (FileNotFoundException ex) {<br>                throw new WebServerException(<br>                        &quot;Could not load trust store: &quot; + ex.getMessage(), ex);<br>            }<br>        }<br>        protocol.setTruststorePass(ssl.getTrustStorePassword());<br>        if (ssl.getTrustStoreType() != null) {<br>            protocol.setTruststoreType(ssl.getTrustStoreType());<br>        }<br>        if (ssl.getTrustStoreProvider() != null) {<br>            protocol.setTruststoreProvider(ssl.getTrustStoreProvider());<br>        }<br>    }</pre><pre>}</pre><p>3. Create class SslStoreProviderUrlStreamHandlerFactory. This is an URLStreamHandlerFactory that provides an URLStreamHandler for accessing an SSLStoreProvider’s key store and trust store from a URL.</p><pre>package com.demo.https;</pre><pre>import java.io.ByteArrayInputStream;<br>import java.io.ByteArrayOutputStream;<br>import java.io.IOException;<br>import java.io.InputStream;<br>import java.net.URL;<br>import java.net.URLConnection;<br>import java.net.URLStreamHandler;<br>import java.net.URLStreamHandlerFactory;<br>import java.security.KeyStore;</pre><pre>import org.springframework.boot.web.server.SslStoreProvider;</pre><pre>class SslStoreProviderUrlStreamHandlerFactory implements URLStreamHandlerFactory {</pre><pre>private static final String PROTOCOL = &quot;springbootssl&quot;;</pre><pre>private static final String KEY_STORE_PATH = &quot;keyStore&quot;;</pre><pre>static final String KEY_STORE_URL = PROTOCOL + &quot;:&quot; + KEY_STORE_PATH;</pre><pre>private static final String TRUST_STORE_PATH = &quot;trustStore&quot;;</pre><pre>static final String TRUST_STORE_URL = PROTOCOL + &quot;:&quot; + TRUST_STORE_PATH;</pre><pre>private final SslStoreProvider sslStoreProvider;</pre><pre>SslStoreProviderUrlStreamHandlerFactory(SslStoreProvider sslStoreProvider) {<br>        this.sslStoreProvider = sslStoreProvider;<br>    }</pre><pre><a href="http://twitter.com/Override">@Override</a><br>    public URLStreamHandler createURLStreamHandler(String protocol) {<br>        if (PROTOCOL.equals(protocol)) {<br>            return new URLStreamHandler() {</pre><pre><a href="http://twitter.com/Override">@Override</a><br>                protected URLConnection openConnection(URL url) throws IOException {<br>                    try {<br>                        if (KEY_STORE_PATH.equals(url.getPath())) {<br>                            return new KeyStoreUrlConnection(url,<br>                                    SslStoreProviderUrlStreamHandlerFactory.this.sslStoreProvider<br>                                            .getKeyStore());<br>                        }<br>                        if (TRUST_STORE_PATH.equals(url.getPath())) {<br>                            return new KeyStoreUrlConnection(url,<br>                                    SslStoreProviderUrlStreamHandlerFactory.this.sslStoreProvider<br>                                            .getTrustStore());<br>                        }<br>                    }<br>                    catch (Exception ex) {<br>                        throw new IOException(ex);<br>                    }<br>                    throw new IOException(&quot;Invalid path: &quot; + url.getPath());<br>                }<br>            };<br>        }<br>        return null;<br>    }</pre><pre>private static final class KeyStoreUrlConnection extends URLConnection {</pre><pre>private final KeyStore keyStore;</pre><pre>private KeyStoreUrlConnection(URL url, KeyStore keyStore) {<br>            super(url);<br>            this.keyStore = keyStore;<br>        }</pre><pre><a href="http://twitter.com/Override">@Override</a><br>        public void connect() throws IOException {</pre><pre>}</pre><pre><a href="http://twitter.com/Override">@Override</a><br>        public InputStream getInputStream() throws IOException {</pre><pre>try {<br>          ByteArrayOutputStream stream = new ByteArrayOutputStream();<br>                this.keyStore.store(stream, new char[0]);<br>                return new ByteArrayInputStream(stream.toByteArray());<br>            }<br>            catch (Exception ex) {<br>                throw new IOException(ex);<br>            }<br>        }</pre><pre>}</pre><pre>}</pre><p>And that’s it! Do let us know if it works for you or either way. Happy learning!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=68fb03243852" width="1" height="1" alt=""><hr><p><a href="https://medium.com/stuff-technology/how-to-enable-https-in-spring-boot-application-68fb03243852">How To Enable HTTPS In Spring Boot Application</a> was originally published in <a href="https://medium.com/stuff-technology">STUFF.TECHNOLOGY</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>