{"id":231775,"date":"2025-01-09T05:16:33","date_gmt":"2025-01-09T13:16:33","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/java\/?p=231775"},"modified":"2025-01-09T05:16:33","modified_gmt":"2025-01-09T13:16:33","slug":"mwa-pattern-strangler-fig","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/java\/mwa-pattern-strangler-fig\/","title":{"rendered":"MWA pattern: Strangler Fig"},"content":{"rendered":"<p dir=\"auto\"><a href=\"https:\/\/github.com\/roryp\/stranglerfig\/blob\/main\/Picture1.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" src=\"https:\/\/github.com\/roryp\/stranglerfig\/raw\/main\/Picture1.png\" alt=\"Strangler Fig\" \/><\/a><\/p>\n<p dir=\"auto\">Author\u2019s Note: After announcing the Modern Web App (MWA) pattern (<a href=\"https:\/\/devblogs.microsoft.com\/java\/introducing-the-modern-web-app-mwa-pattern-for-java\" rel=\"nofollow\">https:\/\/devblogs.microsoft.com\/java\/introducing-the-modern-web-app-mwa-pattern-for-java<\/a>), we now focus on one of its many pattens &#8211; the Strangler Fig pattern. This pattern incrementally modernizes a legacy Java application by \u201cstrangling\u201d targeted areas and replacing them with new microservices or minimal web apps. We\u2019ll explore an example showing how to integrate this approach and smoothly transition from a monolith to modern microservices.<\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h1 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">MWA pattern: Strangler Fig<\/h1>\n<\/div>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h2 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Introduction<\/h2>\n<\/div>\n<p dir=\"auto\">In today&#8217;s fast-paced technological landscape, modernizing Java applications is crucial for achieving scalability, maintainability, and performance. Legacy systems often struggle to keep up with the demands of modern users and evolving business requirements. By adopting modern architectural patterns, organizations can ensure their applications remain competitive and capable of handling increased workloads.<\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h2 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">The Strangler Fig Pattern: A Strategy for Incremental Modernization<\/h2>\n<\/div>\n<p dir=\"auto\">As applications age, the tools, technologies, and architectures they rely on can become outdated. Introducing new features can increase complexity, making these systems harder to maintain and evolve. Completely rewriting a complex system is often a massive and risky undertaking. The\u00a0<strong>Strangler Fig Pattern<\/strong>\u00a0offers a solution by allowing you to incrementally migrate a legacy system. This is achieved by gradually replacing specific pieces of functionality with new applications and services.<\/p>\n<p dir=\"auto\">Inspired by the strangler fig tree that grows around and eventually replaces its host, this pattern involves creating a fa\u00e7ade that intercepts requests to the backend legacy system. The fa\u00e7ade routes these requests either to the legacy application or the new services. This approach enables existing features to be migrated gradually, while consumers continue using the same interface, unaware of the changes happening behind the scenes.<\/p>\n<p dir=\"auto\">By gradually replacing the legacy system&#8217;s features, the new system eventually encompasses all functionalities, allowing you to safely decommission the old system.<\/p>\n<p dir=\"auto\"><em>Read Martin Fowler&#8217;s original article on the Strangler Fig Application\u00a0<a href=\"https:\/\/martinfowler.com\/bliki\/StranglerFigApplication.html\" rel=\"nofollow\">here<\/a>.<\/em><\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h3 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Example<\/h3>\n<\/div>\n<p dir=\"auto\">Next let&#8217;s look at a typical use case where the Strangler Fig pattern would make a good fit. Imagine you&#8217;re migrating a\u00a0<code>\/customer<\/code>\u00a0endpoint from a legacy system to a modernized architecture. You can deploy a router that directs requests to either the old or new implementation based on specific conditions.<\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h4 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Java Code Example<\/h4>\n<\/div>\n<div class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre><span class=\"pl-c1\">@<\/span><span class=\"pl-c1\">RestController<\/span>\r\n<span class=\"pl-c1\">@<\/span><span class=\"pl-c1\">RequestMapping<\/span>(<span class=\"pl-s\">\"\/api\"<\/span>)\r\n<span class=\"pl-k\">public<\/span> <span class=\"pl-k\">class<\/span> <span class=\"pl-smi\">CustomerRouterController<\/span> {\r\n    <span class=\"pl-k\">private<\/span> <span class=\"pl-k\">final<\/span> <span class=\"pl-smi\">LegacyCustomerService<\/span> <span class=\"pl-s1\">legacyService<\/span>;\r\n    <span class=\"pl-k\">private<\/span> <span class=\"pl-k\">final<\/span> <span class=\"pl-smi\">ModernCustomerService<\/span> <span class=\"pl-s1\">modernService<\/span>;\r\n\r\n    <span class=\"pl-k\">public<\/span> <span class=\"pl-smi\">CustomerRouterController<\/span>(<span class=\"pl-smi\">LegacyCustomerService<\/span> <span class=\"pl-s1\">legacyService<\/span>, <span class=\"pl-smi\">ModernCustomerService<\/span> <span class=\"pl-s1\">modernService<\/span>) {\r\n        <span class=\"pl-smi\">this<\/span>.<span class=\"pl-s1\">legacyService<\/span> = <span class=\"pl-s1\">legacyService<\/span>;\r\n        <span class=\"pl-smi\">this<\/span>.<span class=\"pl-s1\">modernService<\/span> = <span class=\"pl-s1\">modernService<\/span>;\r\n    }\r\n\r\n    <span class=\"pl-c1\">@<\/span><span class=\"pl-c1\">GetMapping<\/span>(<span class=\"pl-s\">\"\/customer\"<\/span>)\r\n    <span class=\"pl-k\">public<\/span> <span class=\"pl-smi\">ResponseEntity<\/span>&lt;<span class=\"pl-smi\">Customer<\/span>&gt; <span class=\"pl-en\">getCustomer<\/span>(<span class=\"pl-c1\">@<\/span><span class=\"pl-c1\">RequestParam<\/span> <span class=\"pl-smi\">String<\/span> <span class=\"pl-s1\">id<\/span>) {\r\n        <span class=\"pl-k\">if<\/span> (<span class=\"pl-en\">isModernCustomer<\/span>(<span class=\"pl-s1\">id<\/span>)) {\r\n            <span class=\"pl-smi\">Customer<\/span> <span class=\"pl-s1\">customer<\/span> = <span class=\"pl-s1\">modernService<\/span>.<span class=\"pl-en\">getCustomerById<\/span>(<span class=\"pl-s1\">id<\/span>);\r\n            <span class=\"pl-k\">return<\/span> <span class=\"pl-smi\">ResponseEntity<\/span>.<span class=\"pl-en\">ok<\/span>(<span class=\"pl-s1\">customer<\/span>);\r\n        }\r\n        <span class=\"pl-smi\">Customer<\/span> <span class=\"pl-s1\">customer<\/span> = <span class=\"pl-s1\">legacyService<\/span>.<span class=\"pl-en\">getCustomerById<\/span>(<span class=\"pl-s1\">id<\/span>);\r\n        <span class=\"pl-k\">return<\/span> <span class=\"pl-smi\">ResponseEntity<\/span>.<span class=\"pl-en\">ok<\/span>(<span class=\"pl-s1\">customer<\/span>);\r\n    }\r\n\r\n    <span class=\"pl-k\">private<\/span> <span class=\"pl-smi\">boolean<\/span> <span class=\"pl-en\">isModernCustomer<\/span>(<span class=\"pl-smi\">String<\/span> <span class=\"pl-s1\">id<\/span>) {\r\n        <span class=\"pl-c\">\/\/ Logic to determine if the request should be routed to the modern service<\/span>\r\n        <span class=\"pl-k\">return<\/span> <span class=\"pl-s1\">id<\/span>.<span class=\"pl-en\">startsWith<\/span>(<span class=\"pl-s\">\"MODERN_\"<\/span>);\r\n    }\r\n}<\/pre>\n<\/div>\n<p dir=\"auto\">This example uses a centralized router to direct requests based on specific criteria, such as the format of the customer ID. It enables both legacy and modern systems to coexist during the transition period. Follow these steps to run the Spring Boot example demonstrating the Strangler Fig pattern.<\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h3 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Prerequisites<\/h3>\n<\/div>\n<p dir=\"auto\">Ensure you have the following tools installed:<\/p>\n<ul dir=\"auto\">\n<li><strong>JDK 17<\/strong>:\u00a0<a href=\"https:\/\/www.oracle.com\/java\/technologies\/javase-jdk17-downloads.html\" rel=\"nofollow\">Download<\/a><\/li>\n<li><strong>Apache Maven<\/strong>:\u00a0<a href=\"https:\/\/maven.apache.org\/download.cgi\" rel=\"nofollow\">Download<\/a><\/li>\n<li><strong>Visual Studio Code<\/strong>:\u00a0<a href=\"https:\/\/code.visualstudio.com\/Download\" rel=\"nofollow\">Download<\/a><\/li>\n<li><strong>Java Extension Pack for Visual Studio Code<\/strong>:\u00a0<a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=vscjava.vscode-java-pack\" rel=\"nofollow\">Marketplace<\/a><\/li>\n<\/ul>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h3 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Steps to Run<\/h3>\n<\/div>\n<ol dir=\"auto\">\n<li>\n<p dir=\"auto\"><strong>Clone the Repository<\/strong><\/p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre>git clone https:\/\/github.com\/roryp\/stranglerfig.git\r\n<span class=\"pl-c1\">cd<\/span> stranglerfig<\/pre>\n<\/div>\n<\/li>\n<li>\n<p dir=\"auto\"><strong>Build the Project<\/strong><\/p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre>mvn clean install<\/pre>\n<\/div>\n<\/li>\n<li>\n<p dir=\"auto\"><strong>Run the Application<\/strong><\/p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre>mvn spring-boot:run<\/pre>\n<\/div>\n<p dir=\"auto\">The application starts on port 8080 by default.<\/p>\n<\/li>\n<li>\n<p dir=\"auto\"><strong>Test the Application<\/strong><\/p>\n<p dir=\"auto\">Send requests to the\u00a0<code>\/api\/customer<\/code>\u00a0endpoint:<\/p>\n<ul dir=\"auto\">\n<li>\n<p dir=\"auto\"><strong>Modern Customer ID<\/strong><\/p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre>curl http:\/\/localhost:8080\/api\/customer<span class=\"pl-k\">?<\/span>id=MODERN_1<\/pre>\n<\/div>\n<p dir=\"auto\">This request is routed to the modern customer service based on the customer ID prefix e.g &#8220;MODERN_&#8221;.<\/p>\n<\/li>\n<li>\n<p dir=\"auto\"><strong>Legacy Customer IDs<\/strong><\/p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre>curl http:\/\/localhost:8080\/api\/customer<span class=\"pl-k\">?<\/span>id=LEGACY_1<\/pre>\n<\/div>\n<p dir=\"auto\">These requests are routed to the legacy customer service based on the customer ID prefix e.g &#8220;LEGACY_&#8221;.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h2 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Modern Java Web App (MWA) Pattern<\/h2>\n<\/div>\n<p dir=\"auto\">Now that the Strangler Fig pattern has been introduced, it can be combined with other techniques to form the\u00a0<strong>MWA Pattern<\/strong>. The MWA pattern emphasizes resilience, security, and scalability, leveraging cloud-native services and best practices. To centrally manage application settings, it uses\u00a0<a href=\"https:\/\/azure.microsoft.com\/services\/app-configuration\/\" rel=\"nofollow\">Azure App Configuration<\/a>, which supports feature toggling and the gradual rollout of new features.<\/p>\n<p dir=\"auto\">Next, let&#8217;s see how to add Azure App Configuration to a typical Spring Boot application:<\/p>\n<ol dir=\"auto\">\n<li>\n<p dir=\"auto\"><strong>Add the Dependency<\/strong>\u00a0to your\u00a0<code>pom.xml<\/code>:<\/p>\n<div class=\"highlight highlight-text-xml notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre>&lt;<span class=\"pl-ent\">dependency<\/span>&gt;\r\n    &lt;<span class=\"pl-ent\">groupId<\/span>&gt;com.azure.spring&lt;\/<span class=\"pl-ent\">groupId<\/span>&gt;\r\n    &lt;<span class=\"pl-ent\">artifactId<\/span>&gt;azure-spring-cloud-feature-management-web&lt;\/<span class=\"pl-ent\">artifactId<\/span>&gt;\r\n    &lt;<span class=\"pl-ent\">version<\/span>&gt;2.3.0&lt;\/<span class=\"pl-ent\">version<\/span>&gt;\r\n&lt;\/<span class=\"pl-ent\">dependency<\/span>&gt;<\/pre>\n<\/div>\n<\/li>\n<li>\n<p dir=\"auto\"><strong>Configure Connection Settings<\/strong>\u00a0in\u00a0<code>application.properties<\/code>:<\/p>\n<div class=\"highlight highlight-source-ini notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre>spring.cloud.azure.appconfiguration.stores[0].<span class=\"pl-k\">endpoint<\/span>=https:\/\/&lt;your-app-config-name&gt;.azconfig.io\r\nspring.cloud.azure.appconfiguration.stores[0].<span class=\"pl-k\">connection-string<\/span>=&lt;your-connection-string&gt;<\/pre>\n<\/div>\n<\/li>\n<li>\n<p dir=\"auto\"><strong>Example Feature Flag<\/strong><\/p>\n<div class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre><span class=\"pl-c1\">@<\/span><span class=\"pl-c1\">RestController<\/span>\r\n<span class=\"pl-c1\">@<\/span><span class=\"pl-c1\">RequestMapping<\/span>(<span class=\"pl-s\">\"\/api\"<\/span>)\r\n<span class=\"pl-k\">public<\/span> <span class=\"pl-k\">class<\/span> <span class=\"pl-smi\">FeatureFlagController<\/span> {\r\n\r\n    <span class=\"pl-c1\">@<\/span><span class=\"pl-c1\">GetMapping<\/span>(<span class=\"pl-s\">\"\/feature\"<\/span>)\r\n    <span class=\"pl-c1\">@<\/span><span class=\"pl-c1\">FeatureGate<\/span>(<span class=\"pl-s1\">feature<\/span> = <span class=\"pl-s\">\"BetaFeature\"<\/span>)\r\n    <span class=\"pl-k\">public<\/span> <span class=\"pl-smi\">ResponseEntity<\/span>&lt;<span class=\"pl-smi\">String<\/span>&gt; <span class=\"pl-en\">getFeature<\/span>() {\r\n        <span class=\"pl-k\">return<\/span> <span class=\"pl-smi\">ResponseEntity<\/span>.<span class=\"pl-en\">ok<\/span>(<span class=\"pl-s\">\"Beta Feature is enabled!\"<\/span>);\r\n    }\r\n}<\/pre>\n<\/div>\n<\/li>\n<\/ol>\n<p dir=\"auto\">With this example, the\u00a0<code>\/feature<\/code>\u00a0endpoint will only be active if the\u00a0<code>BetaFeature<\/code>\u00a0flag is enabled in Azure App Configuration.<\/p>\n<p dir=\"auto\">Next, explore our end-to-end (with great focus on Strangler Fig and Azure App Config) MWA reference example:<\/p>\n<ol dir=\"auto\">\n<li>Clone the\u00a0<a href=\"https:\/\/github.com\/azure\/modern-web-app-pattern-java\">MWA respository<\/a><\/li>\n<li>Deploy the App using\u00a0<code>azd up<\/code><\/li>\n<li>Real-time migrate an Azure App using the Strangler Fig Pattern &#8211;\u00a0<a href=\"https:\/\/github.com\/Azure\/modern-web-app-pattern-java\/blob\/main\/demo.md\">demo.md<\/a><\/li>\n<\/ol>\n<p dir=\"auto\"><a href=\"https:\/\/github.com\/roryp\/stranglerfig\/blob\/main\/docs\/architecture.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" src=\"https:\/\/github.com\/roryp\/stranglerfig\/raw\/main\/docs\/architecture.png\" alt=\"Architecture\" \/><\/a><\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h2 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Conclusion<\/h2>\n<\/div>\n<p dir=\"auto\">Modernizing Java applications using the Strangler Fig pattern and the Modern Web App (MWA) pattern provides a strategic approach to incrementally evolve legacy systems. By leveraging these patterns, organizations can achieve scalability, maintainability, and performance while minimizing risks and ensuring continuous availability. Start your modernization journey today by adopting these proven architectural patterns with the help of the\u00a0<a href=\"https:\/\/github.com\/azure\/modern-web-app-pattern-java\">Modern Java Web App Patterns Repository<\/a><\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h2 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Useful Links<\/h2>\n<\/div>\n<ol dir=\"auto\">\n<li>Deploy the Reference App: Experience all MWA principles in action by deploying the full production-grade Java application to Azure. Visit the\u00a0<a href=\"https:\/\/github.com\/Azure\/modern-web-app-pattern-java\">MWA GitHub repository<\/a>\u00a0for more information.<\/li>\n<li>Explore In-Depth Documentation: Learn more about MWA through comprehensive\u00a0<a href=\"https:\/\/aka.ms\/eap\/mwa\/java\/doc\" rel=\"nofollow\">documentation<\/a>\u00a0on Microsoft Learn.<\/li>\n<li><a href=\"https:\/\/aka.ms\/eap\/mwa\/java\/demo\" rel=\"nofollow\">Try Out MWA Patterns<\/a>: Discover and experiment with the MWA patterns to modernize and scale your Java applications<\/li>\n<li>Source code for this blog: <a href=\"https:\/\/github.com\/roryp\/stranglerfig\">roryp\/stranglerfig: Modernizing Java Applications with the Strangler and Modern Web App Patterns<\/a><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Author\u2019s Note: After announcing the Modern Web App (MWA) pattern (https:\/\/devblogs.microsoft.com\/java\/introducing-the-modern-web-app-mwa-pattern-for-java), we now focus on one of its many pattens &#8211; the Strangler Fig pattern. This pattern incrementally modernizes a legacy Java application by \u201cstrangling\u201d targeted areas and replacing them with new microservices or minimal web apps. We\u2019ll explore an example showing how to integrate [&hellip;]<\/p>\n","protected":false},"author":29534,"featured_media":227205,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-231775","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java"],"acf":[],"blog_post_summary":"<p>Author\u2019s Note: After announcing the Modern Web App (MWA) pattern (https:\/\/devblogs.microsoft.com\/java\/introducing-the-modern-web-app-mwa-pattern-for-java), we now focus on one of its many pattens &#8211; the Strangler Fig pattern. This pattern incrementally modernizes a legacy Java application by \u201cstrangling\u201d targeted areas and replacing them with new microservices or minimal web apps. We\u2019ll explore an example showing how to integrate [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/java\/wp-json\/wp\/v2\/posts\/231775","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/java\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/java\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/java\/wp-json\/wp\/v2\/users\/29534"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/java\/wp-json\/wp\/v2\/comments?post=231775"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/java\/wp-json\/wp\/v2\/posts\/231775\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/java\/wp-json\/wp\/v2\/media\/227205"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/java\/wp-json\/wp\/v2\/media?parent=231775"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/java\/wp-json\/wp\/v2\/categories?post=231775"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/java\/wp-json\/wp\/v2\/tags?post=231775"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}