diff --git a/_data/events.json b/_data/events.json index d7f255d64a6..dd3d08ef746 100644 --- a/_data/events.json +++ b/_data/events.json @@ -1,5 +1,37 @@ { "events": [ + { + "date": "October 26, 2023", + "day": "Thur.", + "time": "6.00 p.m. EAT", + "expire": "2023-10-27T00:00:00.0000-00:00", + "location": "Virtual", + "url": "https://summit.africastalking.com/#speakers", + "eventType": "Africa's Talking Summit", + "eventName": "Empowering Integration Development with Ballerina: A Developer's Perspective", + "presenterTwitter": "https://twitter.com/pcnfernando", + "presenter": "Chiran Fernando", + "presenterDesignation": "Associate Technical Lead, WSO2", + "otherInfo": "", + "videoURL": "", + "buttonText": "More info" + }, + { + "date": "October 24, 2023", + "day": "Tue.", + "time": "9.30 a.m. IST", + "expire": "2023-10-25T00:00:00.0000-00:00", + "location": "Virtual", + "url": "https://www.meetup.com/ballerinalang-community/events/296693791/", + "eventType": "Ballerina Tech Talk", + "eventName": "The Developer's Journey: Building Integrations the Ballerina Way (Part 2)", + "presenterTwitter": "https://twitter.com/sameerajayasoma", + "presenter": "Sameera Jayasoma", + "presenterDesignation": "Ballerina Platform Architect", + "otherInfo": "", + "videoURL": "", + "buttonText": "More info" + }, { "date": "October 1-31, 2023", "day": "", @@ -29,8 +61,8 @@ "presenter": "Shafreen Anfar", "presenterDesignation": "Associate Director, WSO2", "otherInfo": "", - "videoURL": "", - "buttonText": "More info" + "videoURL": "https://www.youtube.com/live/qierfHRpn6I?si=YoKe4y3hYJP_b6Qv&t=7075", + "buttonText": "Watch recording" }, { "date": "September 28, 2023", @@ -61,8 +93,8 @@ "presenter": "Sameera Jayasoma", "presenterDesignation": "Ballerina Platform Architect", "otherInfo": "", - "videoURL": "", - "buttonText": "More info" + "videoURL": "https://www.youtube.com/watch?v=CJm_Z2CDEQ8", + "buttonText": "Watch recording" }, { "date": "August 17, 2023", diff --git a/_data/release_notes_versions.json b/_data/release_notes_versions.json index 31846280b17..a47fb4bdf89 100644 --- a/_data/release_notes_versions.json +++ b/_data/release_notes_versions.json @@ -1302,5 +1302,23 @@ ], "api-docs": "ballerina-api-docs-1.2.44.zip", "release-notes": "ballerina-release-notes-1.2.44.md" + }, + { + "version": "1.2.45", + "release-date": "2023-10-15", + "windows-installer": "ballerina-windows-installer-x64-1.2.45.msi", + "windows-installer-size": "148mb", + "linux-installer": "ballerina-linux-installer-x64-1.2.45.deb", + "linux-installer-size": "145mb", + "macos-installer": "ballerina-macos-installer-x64-1.2.45.pkg", + "macos-installer-size": "165mb", + "rpm-installer": "ballerina-linux-installer-x64-1.2.45.rpm", + "rpm-installer-size": "168mb", + "other-artefacts": [ + "ballerina-1.2.45.zip", + "ballerina-1.2.45.vsix" + ], + "api-docs": "ballerina-api-docs-1.2.45.zip", + "release-notes": "ballerina-release-notes-1.2.45.md" } -] +] \ No newline at end of file diff --git a/_data/stable-latest/metadata.json b/_data/stable-latest/metadata.json index c49cb8ca4bc..d9006b00e31 100644 --- a/_data/stable-latest/metadata.json +++ b/_data/stable-latest/metadata.json @@ -1,17 +1,18 @@ { - "version":"1.2.44", - "release-date":"2023-08-23", - "windows-installer":"ballerina-windows-installer-x64-1.2.44.msi", - "windows-installer-size":"149mb", - "linux-installer":"ballerina-linux-installer-x64-1.2.44.deb", + "version":"1.2.45", + "release-date":"2023-10-15", + "windows-installer":"ballerina-windows-installer-x64-1.2.45.msi", + "windows-installer-size":"148mb", + "linux-installer":"ballerina-linux-installer-x64-1.2.45.deb", "linux-installer-size":"145mb", - "macos-installer":"ballerina-macos-installer-x64-1.2.44.pkg", + "macos-installer":"ballerina-macos-installer-x64-1.2.45.pkg", "macos-installer-size":"165mb", - "rpm-installer":"ballerina-linux-installer-x64-1.2.44.rpm", + "rpm-installer":"ballerina-linux-installer-x64-1.2.45.rpm", "rpm-installer-size":"168mb", "other-artefacts":[ - "ballerina-1.2.44.zip" + "ballerina-1.2.45.zip", + "ballerina-1.2.45.vsix" ], - "api-docs":"ballerina-api-docs-1.2.44.zip", - "release-notes":"ballerina-release-notes-1.2.44.md" + "api-docs":"ballerina-api-docs-1.2.45.zip", + "release-notes":"ballerina-release-notes-1.2.45.md" } diff --git a/_data/swanlake-latest/metadata.json b/_data/swanlake-latest/metadata.json index b20bf65765c..5eb7ed0e980 100644 --- a/_data/swanlake-latest/metadata.json +++ b/_data/swanlake-latest/metadata.json @@ -1,21 +1,21 @@ { - "version":"2201.8.1", - "short-version":"2201.8.1", - "display-version":"2201.8.1 (Swan Lake Update 8)", - "release-date":"2023-10-07", - "windows-installer":"ballerina-2201.8.1-swan-lake-windows-x64.msi", - "windows-installer-size":"176mb", - "linux-installer":"ballerina-2201.8.1-swan-lake-linux-x64.deb", + "version":"2201.8.2", + "short-version":"2201.8.2", + "display-version":"2201.8.2 (Swan Lake Update 8)", + "release-date":"2023-10-17", + "windows-installer":"ballerina-2201.8.2-swan-lake-windows-x64.msi", + "windows-installer-size":"174mb", + "linux-installer":"ballerina-2201.8.2-swan-lake-linux-x64.deb", "linux-installer-size":"197mb", - "macos-installer":"ballerina-2201.8.1-swan-lake-macos-x64.pkg", + "macos-installer":"ballerina-2201.8.2-swan-lake-macos-x64.pkg", "macos-installer-size":"232mb", - "macos-arm-installer":"ballerina-2201.8.1-swan-lake-macos-arm-x64.pkg", + "macos-arm-installer":"ballerina-2201.8.2-swan-lake-macos-arm-x64.pkg", "macos-arm-installer-size":"231mb", - "rpm-installer":"ballerina-2201.8.1-swan-lake-linux-x64.rpm", + "rpm-installer":"ballerina-2201.8.2-swan-lake-linux-x64.rpm", "rpm-installer-size":"234mb", - "other-artefacts":[ - "ballerina-2201.8.1-swan-lake.zip" - ], - "api-docs":"ballerina-api-docs-2201.8.1.zip", - "release-notes":"ballerina-release-notes-2201.8.1.md" + "other-artefacts":[ + "ballerina-2201.8.2-swan-lake.zip" + ], + "api-docs":"ballerina-api-docs-2201.8.2.zip", + "release-notes":"ballerina-release-notes-2201.8.2.md" } diff --git a/_data/swanlake_release_notes_versions.json b/_data/swanlake_release_notes_versions.json index e8910a85ad5..f301d129a3b 100644 --- a/_data/swanlake_release_notes_versions.json +++ b/_data/swanlake_release_notes_versions.json @@ -990,5 +990,26 @@ ], "api-docs":"ballerina-api-docs-2201.8.0.zip", "release-notes":"ballerina-release-notes-2201.8.0.md" +}, +{ + "version":"2201.8.1", + "short-version":"2201.8.1", + "display-version":"2201.8.1 (Swan Lake Update 8)", + "release-date":"2023-10-07", + "windows-installer":"ballerina-2201.8.1-swan-lake-windows-x64.msi", + "windows-installer-size":"176mb", + "linux-installer":"ballerina-2201.8.1-swan-lake-linux-x64.deb", + "linux-installer-size":"197mb", + "macos-installer":"ballerina-2201.8.1-swan-lake-macos-x64.pkg", + "macos-installer-size":"232mb", + "macos-arm-installer":"ballerina-2201.8.1-swan-lake-macos-arm-x64.pkg", + "macos-arm-installer-size":"231mb", + "rpm-installer":"ballerina-2201.8.1-swan-lake-linux-x64.rpm", + "rpm-installer-size":"234mb", + "other-artefacts":[ + "ballerina-2201.8.1-swan-lake.zip" + ], + "api-docs":"ballerina-api-docs-2201.8.1.zip", + "release-notes":"ballerina-release-notes-2201.8.1.md" } ] diff --git a/case-studies/mosip.md b/case-studies/mosip.md index 378e7147df5..13f32e44f15 100644 --- a/case-studies/mosip.md +++ b/case-studies/mosip.md @@ -7,6 +7,7 @@ permalink: /learn/case-studies/mosip active: mosip intro: Ballerina is an open source programming language for the cloud that makes it easier to use, combine, and create network services. In addition to the powerful language features, it comes with a rich Ballerina library, which covers network data, messaging, and communication protocols. The Modular Open Source Identity Platform (MOSIP), an open-source identity platform currently being adopted by several countries to manage the digitization of their civil registries, uses the Ballerina WebSubHub module for event-driven communication. logo: '/images/home-page/user-logos/mosip.png' +user: 'mosip' --- ## Overview diff --git a/case-studies/wso2.md b/case-studies/wso2.md index f7b09a69742..cf02e8a8086 100644 --- a/case-studies/wso2.md +++ b/case-studies/wso2.md @@ -7,6 +7,7 @@ permalink: /learn/case-studies/wso2 active: wso2 intro: WSO2’s digital transformation team realized that they needed to modernize the company’s own internal applications to improve operational efficiency, collaboration, and productivity. To drive these efforts, the company leveraged the Ballerina language to achieve remarkable results and empower its workforce. logo: '/images/home-page/user-logos/wso2.svg' +user: 'wso2' --- ## Overview diff --git a/community/newsletter/2023-4.md b/community/newsletter/2023-4.md new file mode 100644 index 00000000000..11721906d43 --- /dev/null +++ b/community/newsletter/2023-4.md @@ -0,0 +1,148 @@ +--- +layout: ballerina-newsletter +issue: "2023 Issue #4 - September" +title: "Insightful comparisons, use cases, training, and more!" +description: This is a periodic newsletter on Ballerina with hand-picked content and regular updates on the language. +keywords: ballerina, community, ballerina community, newsletter +permalink: /community/newsletter/2023-4/ +--- + + + + + + + +
+ + + + +

2023 Issue #4 - September

+ +

This is a recurring newsletter of content around Ballerina and related technology topics such as integration, microservices, distributed systems, and cloud computing.
+ Not a subscriber yet? Sign up here.

+ +

Comparing Ballerina Swan Lake

+ +

Apollo vs. Ballerina Swan Lake for GraphQL

+ +

In this first comparison, we look at both Apollo and Ballerina for implementing GraphQL APIs. GraphQL's flexibility, efficient data fetching, and improved developer experience are some of the few reasons that make it a powerful choice for implementing the backend for frontend (BFF) architecture, providing enhanced performance and simplified data management for frontend applications. Learn why Ballerina Swan Lake is an excellent choice for GraphQL due to its GraphQL-friendly abstractions.

+ +

Java vs. Ballerina Swan Lake for data-oriented programming

+ +

We next compare Ballerina and Java for data-oriented programming, which is crucial in modern software development due to its complexity and data-intensive nature of applications. Read this comparison to discover the power of Ballerina Swan Lake for data-oriented programming and see why it comes up on top for efficient data handling and processing.

+ +

New use cases: Data-oriented programming, EDA, and B2B

+ +

Check out our latest use case on data-oriented programming with Ballerina Swan Lake and discover the seamless synergy between the language and data, enabling an optimized approach to handle complex data scenarios.

+ +

Explore Ballerina’s Event-Driven Architecture (EDA) capabilities. Whether it's event streaming, data integration, or building reactive systems, Ballerina empowers developers with a seamless EDA experience.

+ +

Did you know that Ballerina Swan Lake is the only language with native support for B2B integrations? It enables a seamless exchange of business data with partner networks using standard formats like X12, EDIFACT, and custom EDI formats.

+ +

Latest training videos

+ +

Whether you're a seasoned programmer or just starting your coding journey, these training videos crafted by the Ballerina team cater to all skill levels and provide a comprehensive understanding of Ballerina Swan Lake.

+ + + +

The three playlists above by Sasindu Alahakoon offer an introduction to some basic concepts of Ballerina Swan Lake.

+ + + +

Anjana Supun shows us how to craft and deploy a real-world Ballerina Swan Lake application in Docker and Kubernetes.

+ + + +

Fathima Dilhasha will guide you through the prerequisites for using the Ballerina Swan Lake test framework.

+ +

Upcoming events

+ +

Ballerina Tech Talk - The Developer's Journey: Building Integrations the Ballerina Way

+ +

Tuesday, September 26, 2023 | 9.30 a.m. PDT

+ +

Join Ballerina Platform Architect Sameera Jayasoma at the next Ballerina Tech Talk, where he will discuss the developer workflow process for building integrations with Ballerina Swan Lake. RSVP today and secure your spot.

+ +

Conf42: Kube Native 2023
+ Simplify network services for real-world, cloud-native applications with Ballerina

+ +

Thursday, September 28, 2023 | 10.00 a.m. PDT

+ +

Want to know how Ballerina streamlines cloud app development? Join Ballerina team member Anuruddha Liyanarachchi at Conf42: Kube Native 2023. Subscribe to this virtual event today!

+ +

Past events

+ +

Ballerina Tech Talk | Ballerina meets GraalVM: Empower cloud-native applications

+ +

Ballerina team member Tharmigan Krishnananthalingam showed us how to build GraalVM native executables with Ballerina Swan Lake. Watch the recording today.

+ +

Featured articles

+ +

Here’s the latest list of technical blog posts curated by the Ballerina community:

+ +

Business-to-business integration with Ballerina
+ by Chathura Ekanayake - The author emphasizes the significance of B2B integrations in digital transformation initiatives.

+ +

Ballerina meets GraalVM: From code to native executable
+ by Tharmigan Krishnananthalingam - The author emphasizes the significance of B2B integrations in digital transformation initiatives.

+ +

Unveiling Ballerina GraalVM image: Tackling production issues
+ by Tharmigan Krishnananthalingam - Learn how to engage profiling and monitoring tools with the Ballerina GraalVM image.

+ +

Data modeling and exposing made easy with Ballerina Persist and GraphQL
+ by Shammi Kolonne - Use the Ballerina Persist and GraphQL modules to store and access data in a data store and expose them through an API.

+ +

Build a container with zero effort in zero time with Ballerina Swan Lake
+ by Thevakumar Luheerathan - This guide provides a thorough understanding of containerization.

+ +

Representing graph data structure in Ballerina
+ by Prakanth Thilakaraj - Learn how to create new object types with Ballerina using its type definition syntax.

+ +

Expose a simple Ballerina program as an AWS Lambda Function
+ by Praneesha Chandrasiri - Learn how to expose a simple Ballerina program as an AWS Lambda Function.

+ +

Invoke an Azure Function via a Cosmos DB trigger using Ballerina
+ by Praneesha Chandrasiri - Learn how to use a Cosmos DB connection to invoke an Azure Function, a Ballerina program.

+ +

Ballerina program execution flow
+ by Nadeeshan Dissanayake - Brush up your knowledge on Ballerina packages, modules, and how a Ballerina program is terminated, and understand the language’s program execution flow and module life cycle.

+ +

Transport layer security in Ballerina — SSL/TLS with HTTP
+ by Anupama Pathirage - This blog discusses how to write secure web services and clients using Ballerina and HTTP with SSL/TLS.

+ +

Featured X posts

+ +

This edition highlights Indusara Jayasoma, Chamupathi Gigara and Nicolai Parlog for showing us how they use Ballerina Swan Lake. Thanks again for your support!

+ Featured Tweets @Indusara_j Featured Tweets @gigarahettige Featured Tweets @nipafx + +

Join the community

+ +

Be a part of our growing community by joining the Discord server and following us on X. Mention @ballerinalang with the hashtag #ballerinalang when you tweet about us and have a chance of being featured in our newsletter! Remember to subscribe to our YouTube channel. You can also show us your support by starring Ballerina’s GitHub repo and following us.

+ + +
+

You are receiving this because you signed up for the Ballerina.io newsletter. If you'd like to stop receiving these emails, simply unsubscribe.

+ +

If this email isn't looking quite right, you can view it in your browser. Did someone forward this issue to you? Subscribe at Ballerina.io and get it in your own inbox.

+ +

Github Twitter Discord Slack Youtube Linkedin

+ +

 

+ +

Privacy Policy  |   Terms of Service

+
+ + + + + diff --git a/community/proposals/active-proposals.md b/community/proposals/active-proposals.md index a9476b6c4b4..299b4dd36cf 100644 --- a/community/proposals/active-proposals.md +++ b/community/proposals/active-proposals.md @@ -11,7 +11,7 @@ permalink: /community/active-proposals |Proposal|Author|Comments|Created date|Status| |---|----|----|----|---| |[[Improvement]: Redesign the Ballerina Shell architecture ](https://github.com/ballerina-platform/ballerina-lang/issues/41296)|[nipunayf](https://github.com/nipunayf)|4|2023-08-28|N/A| -|[[New Feature]: Formatting a Ballerina module through project-level configurations](https://github.com/ballerina-platform/ballerina-lang/issues/41280)|[poorna2152](https://github.com/poorna2152)|7|2023-08-23|N/A| +|[[New Feature]: Formatting a Ballerina module through project-level configurations](https://github.com/ballerina-platform/ballerina-lang/issues/41280)|[poorna2152](https://github.com/poorna2152)|11|2023-08-23|N/A| ## [ballerina-distribution](https://github.com/ballerina-platform/ballerina-distribution) diff --git a/community/slides/Ballerina_Language_Presentation-2021-03-08.pdf b/community/slides/Ballerina_Language_Presentation-2021-03-08.pdf new file mode 100644 index 00000000000..ae03995c0be Binary files /dev/null and b/community/slides/Ballerina_Language_Presentation-2021-03-08.pdf differ diff --git a/components/common/footer/Footer.js b/components/common/footer/Footer.js index 6c798d15eda..18a505b939b 100644 --- a/components/common/footer/Footer.js +++ b/components/common/footer/Footer.js @@ -62,7 +62,7 @@ export default function Footer() {
  • - + LinkedIn
  • diff --git a/components/community/resources/other/Other.js b/components/community/resources/other/Other.js index 084c261a939..44607542603 100644 --- a/components/community/resources/other/Other.js +++ b/components/community/resources/other/Other.js @@ -30,7 +30,7 @@ export default function Other() {

    Other resources

    - +

    Language introduction slides

    A high-level overview of the Ballerina language

    diff --git a/components/hacktoberfest/rules/Rules.js b/components/hacktoberfest/rules/Rules.js index 8a1844eb8f1..a6e43466d2a 100644 --- a/components/hacktoberfest/rules/Rules.js +++ b/components/hacktoberfest/rules/Rules.js @@ -68,6 +68,7 @@ export default function Rules(props) {
  • All decisions made by the Ballerina Hacktoberfest panel shall be deemed final, conclusive, and binding.
  • +

    By participating in this competition, you agree to our Terms & Conditions.

    diff --git a/components/home-page/users/Users.js b/components/home-page/users/Users.js index f8ccd4887a1..d58bcc866a4 100644 --- a/components/home-page/users/Users.js +++ b/components/home-page/users/Users.js @@ -50,8 +50,9 @@ export default function Users(props) { WSO2 Choreo + Fat Tuesday MOSIP - Avinya Foundation + QHAna - The Quantum Humanities Analysis Tool @@ -60,7 +61,12 @@ export default function Users(props) { Ballerina Central Redcross Elixir RAAPID + + + + Tech Venturas + Avinya Foundation diff --git a/downloads/1.2.x-release-notes/1.2.45.md b/downloads/1.2.x-release-notes/1.2.45.md new file mode 100644 index 00000000000..9917c848b19 --- /dev/null +++ b/downloads/1.2.x-release-notes/1.2.45.md @@ -0,0 +1,32 @@ +--- +layout: ballerina-left-nav-release-notes +title: 1.2.45 +permalink: /downloads/1.2.x-release-notes/1.2.45/ +active: 1.2.45 +redirect_from: + - /downloads/1.2.x-release-notes/ +--- + +### Overview of jBallerina 1.2.45 + +The jBallerina 1.2.45 patch release improves upon the 1.2.44 release by addressing an [issue](https://github.com/ballerina-platform/ballerina-standard-library/issues/4908). + +You can use the update tool to update to jBallerina 1.2.45 as follows. + +**For existing users:** +If you are already using jBallerina version 1.2.14, or above, you can directly update your distribution to jBallerina 1.2.45 by executing the following command: + +``` +bal dist update +``` + +However, if you are using + +- jBallerina 1.2.0 to 1.2.13, run `ballerina dist update` to update +- jBallerina 1.2.0 but being switched to a previous version, run `ballerina dist pull jballerina-1.2.45` to update +- a jBallerina version below 1.1.0, install via the [installers](https://ballerina.io/downloads/) + +**For new users:** +If you have not installed jBallerina, then download the [installers](https://ballerina.io/downloads/) to install. + + diff --git a/downloads/installation-options.md b/downloads/installation-options.md index a04413e2fd8..792f4cba7ab 100644 --- a/downloads/installation-options.md +++ b/downloads/installation-options.md @@ -93,7 +93,7 @@ For instructions, see + {/* */} - + + {/* */} - + + @@ -128,12 +141,12 @@ export default function PostPage({ frontmatter, content, slug }) { - +

    {frontmatter.intro}

    - +
    diff --git a/pages/learn/by-example/[bbe].js b/pages/learn/by-example/[bbe].js index 19496b2667b..aed2ee49d46 100644 --- a/pages/learn/by-example/[bbe].js +++ b/pages/learn/by-example/[bbe].js @@ -117,12 +117,22 @@ export default function BBEPage({ frontmatter, navContent, bbe, codes }) { property="og:title" content={`Ballerina - ${frontmatter.title}`} /> + {/* */} + + {/* */} - + + diff --git a/pages/learn/by-example/index.js b/pages/learn/by-example/index.js index a1fa12edcfe..ba4ba5aa7e2 100644 --- a/pages/learn/by-example/index.js +++ b/pages/learn/by-example/index.js @@ -166,14 +166,14 @@ {/* LINKED IN */} diff --git a/pages/learn/enterprise-integration-patterns/[pattern].js b/pages/learn/enterprise-integration-patterns/[pattern].js index 8d21a900ed9..763ea2169aa 100644 --- a/pages/learn/enterprise-integration-patterns/[pattern].js +++ b/pages/learn/enterprise-integration-patterns/[pattern].js @@ -44,7 +44,7 @@ export async function getStaticProps({ params }) { return { props: { code, name, content } }; } const yml = fs.readFileSync(ymlPath, "utf-8"); - var props = load(yml); + var props = load(yml) || {}; props.code = code; props.name = props.name ?? name; props.content = content; diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/.gitignore b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/.gitignore deleted file mode 100644 index 46ede0de279..00000000000 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -replay_pid* - -# Build Files -target - -# Ballerina -# Latest versions of dependencies will be used -mock-http/Dependencies.toml diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/canonical-data-model.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/canonical-data-model.bal new file mode 100644 index 00000000000..59d755f3f1d --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/canonical-data-model.bal @@ -0,0 +1,138 @@ +import ballerina/http; + +const PROJECT_ID = "LAND-TEST04"; +const DATASET_ID = "f57074a0-a8b6-403e-9df1-e9fc46"; + +final http:Client gMapClient = check new ("http://mapsplatformdatasets.googleapis.com.balmock.io"); +final http:Client microsoftClient = check new ("http://atlas.microsoft.com.balmock.io"); + +type Gpx xml; + +type Kml xml; + +type Csv record {| + float X; + float Y; + string Name; + string Description; +|}[]; + +type GeoJson record { + string 'type = "FeatureCollection"; + string name = "PlaceMarks"; + Feature[] features; +}; + +type Feature record {| + string 'type = "Feature"; + record {| + string X; + string Y; + string Name; + string description; + |} properties; + record {| + string 'type = "Point"; + string[] coordinates; + |} geometry; +|}; + +type GMapResponse record { + string name; + string displayName; + string createTime; +}; + +type MicrosoftMapResponse record { + string formatVersion; + record { + record { + string latitude; + string longitude; + }[] points; + }[] routes; +}; + +service /map on new http:Listener(8080) { + resource function post uploadPlaceMarks(http:Request request) returns GMapResponse|error? { + Csv|Gpx data = check getPayload(request); + GeoJson geoJson = convertToCanonical(data); + Kml kmlData = convertFromCanonicalToKml(geoJson); + GMapResponse gMapResponse = check gMapClient->post( + string `/v1/projects/${PROJECT_ID}/datasets/${DATASET_ID}:import`, kmlData); + return gMapResponse; + } + + resource function post getRouteDirection(http:Request request, string query) returns MicrosoftMapResponse|error { + Csv|Gpx data = check getPayload(request); + GeoJson geoJson = convertToCanonical(data); + MicrosoftMapResponse microsoftMapResponse = check microsoftClient->/route/directions/'json.post( + {"supportingPoints": geoJson.toJson()}, {query: string `${query}`} + ); + return microsoftMapResponse; + } +} + +isolated function convertToCanonical(Csv|Gpx data) returns GeoJson { + if data is Csv { + return convertFromCsvToCanonical(data); + } else { + return convertFromGpxToCanonical(data); + } +} + +isolated function getPayload(http:Request request) returns Csv|Gpx|error { + if request.getContentType().includes("xml") { + return request.getXmlPayload(); + } + json data = check request.getJsonPayload(); + return data.cloneWithType(Csv); +} + +isolated function convertFromCsvToCanonical(Csv data) returns GeoJson { + return { + features: from var member in data + let string X = member.X.toString(), string Y = member.Y.toString() + select { + properties: {X, Y, Name: member.Name, description: member.Description}, + geometry: {coordinates: [X, Y]} + } + }; +} + +isolated function convertFromGpxToCanonical(Gpx gpxData) returns GeoJson { + return { + features: from var extension in gpxData/**/ + select { + properties: { + X: (extension/**/).data(), + Y: (extension/**/).data(), + Name: (extension/**/).data(), + description: (extension/**/).data() + }, + geometry: {coordinates: [(extension/**/).data(), (extension/**/).data()]} + } + }; +} + +isolated function convertFromCanonicalToKml(GeoJson geoJson) returns Kml { + xml kmlData = xml ` + + + + + + + ${from Feature feature in geoJson.features + select xml ` + ${feature.properties.description} + + + ${feature.geometry.coordinates[0]},${feature.geometry.coordinates[1]} + + + `} + + `; + return kmlData; +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/canonical-data-model.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/canonical-data-model.yml new file mode 100644 index 00000000000..c0bf389a6fe --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/canonical-data-model.yml @@ -0,0 +1,7 @@ +tagline: Common message format for communication between applications +desc: The Canonical Data Model is a common message format used by different applications for communication. +category: Message Transformation +index: 41 +helps: Ballerina provides powerful data modelling capabilities through its Type System. You can define data types like JSON and xml, and structures like records to represent your canonical data model. This ensures interoperability when integrating different components in your system, making it easier to exchange data seamlessly. +tags: ["Canonical Data Model", "Message Router", "Message Translator", "Format Indicator"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/CanonicalDataModel.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/tests/case-01-mapsplatformdatasets.googleapis.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/tests/case-01-mapsplatformdatasets.googleapis.com.balmock.io.json new file mode 100644 index 00000000000..2c26a6fddad --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/tests/case-01-mapsplatformdatasets.googleapis.com.balmock.io.json @@ -0,0 +1,5 @@ +{ + "name": "projects/LAND-TEST04/datasets/f57074a0-a8b6-403e-9df1-e9fc46", + "displayName": "My Test Dataset", + "createTime": "2022-08-15T17:50:00.189682Z" +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/tests/case-01.http b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/tests/case-01.http new file mode 100644 index 00000000000..e8f8513740f --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/tests/case-01.http @@ -0,0 +1,22 @@ +POST http://localhost:8080/map/uploadPlaceMarks + +[ + { + "X": -122.082203542568, + "Y": 37.4222899014025, + "Name": "Simple placemark", + "Description": "Attached to the ground. Intelligently places itself at the height of the underlying terrain." + }, + { + "X": -122.084075, + "Y": 37.4220033612141, + "Name": "Floating placemark", + "Description": "Floats a defined distance above the ground." + }, + { + "X": -122.085766700618, + "Y": 37.4215692786755, + "Name": "Extruded placemark", + "Description": "Tethered to the ground by a customizable tail" + } +] diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/tests/case-02-atlas.microsoft.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/tests/case-02-atlas.microsoft.com.balmock.io.json new file mode 100644 index 00000000000..99029f744c8 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/tests/case-02-atlas.microsoft.com.balmock.io.json @@ -0,0 +1,17 @@ +{ + "formatVersion": "0.0.12", + "routes": [ + { + "points": [ + { + "latitude": "52.50931", + "longitude": "13.42937" + }, + { + "latitude": "52.50904", + "longitude": "13.42912" + } + ] + } + ] +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/tests/case-02.http b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/tests/case-02.http new file mode 100644 index 00000000000..a0042893308 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/canonical-data-model/tests/case-02.http @@ -0,0 +1,32 @@ +POST http://localhost:8080/map/getRouteDirection?query=52.50931,13.42936:52.50274,13.43872 +Content-Type: application/xml + + + + + + -122.082203542568 + 37.4222899014025 + Simple placemark + Attached to the ground. Intelligently places itself at the + height of the underlying terrain. + + + + + -122.084075 + 37.4220033612141 + Floating placemark + Floats a defined distance above the ground. + + + + + -122.085766700618 + 37.4215692786755 + Extruded placemark + Tethered to the ground by a customizable + "tail" + + + diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/channel-adapter/channel-adapter.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/channel-adapter/channel-adapter.bal new file mode 100644 index 00000000000..a1d8ff80981 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/channel-adapter/channel-adapter.bal @@ -0,0 +1,19 @@ +import ballerina/io; +import ballerinax/jira; + +configurable string username = "admin"; +configurable string password = "admin"; + +final jira:ConnectionConfig jiraConfig = { + auth: { + username, + password + } +}; + +final jira:Client jiraAdapter = check new (jiraConfig, "http://wso2.jira.com.balmock.io"); + +public function main() returns error? { + jira:Project result = check jiraAdapter->getProject("EI-Patterns-With-Ballerina"); + io:println(result.toString()); +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/channel-adapter/channel-adapter.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/channel-adapter/channel-adapter.yml new file mode 100644 index 00000000000..c3d27fc2da8 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/channel-adapter/channel-adapter.yml @@ -0,0 +1,7 @@ +tagline: Object to interact with messaging channels +desc: The channel adapter is an interface to interact with a channel. +category: Messaging Channels +index: 12 +helps: Ballerina supports a rich set of Connectors to interact with different applications. Developers can create their connectors and publish them as a package. +tags: ["Channel Adapter", "Message Channel", "Messaging"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/ChannelAdapter.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/channel-adapter/tests/case-01-wso2.jira.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/channel-adapter/tests/case-01-wso2.jira.com.balmock.io.json new file mode 100644 index 00000000000..d7cfb8bdf8e --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/channel-adapter/tests/case-01-wso2.jira.com.balmock.io.json @@ -0,0 +1,22 @@ +{ + "expand": "description,lead,components,issueTypes,url,email,assigneeType,versions,name,roles,projectCategory", + "self": "http://example.com/jira/project/12345", + "id": "12345", + "key": "PROJ123", + "description": "Sample project for demonstration purposes", + "lead": { + "name": "John Doe", + "key": "johndoe", + "emailAddress": "johndoe@example.com" + }, + "components": [ + { + "id": "1", + "name": "Component A" + }, + { + "id": "2", + "name": "Component B" + } + ] +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/claim-check/claim-check-consumer.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/claim-check/claim-check-consumer.bal new file mode 100644 index 00000000000..b412dceb177 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/claim-check/claim-check-consumer.bal @@ -0,0 +1,28 @@ +import ballerina/http; +import ballerina/io; +import ballerinax/kafka; + +type ScanResult [string, string]; + +final http:Client awsS3Client = check new ("http://bucket.s3.amazonaws.com.balmock,io"); +final http:Client firebaseClient = check new ("http://api.mriresults.firebase.com.balmock.io"); +final kafka:Consumer kafkaConsumer = check new (kafka:DEFAULT_URL, { + groupId: "mri-scan-group", + topics: ["topic-mri-scan"] +}); + +public function main() returns error? { + while true { + ScanResult[] mriScanResults = check kafkaConsumer->pollPayload(1); + foreach var [scanId, patientId] in mriScanResults { + http:Response s3Response = check awsS3Client->/mri\-scans/[scanId].get(); + string mriScanResult = analyzeMriScan(check s3Response.getByteStream()); + _ = check firebaseClient->/mri/[scanId]/reports\.json.put({mriScanResult, patientId}, targetType = json); + } + } +} + +isolated function analyzeMriScan(stream fileByteStream) returns string { + // logic to analyze the MRI scan + return "No Abnormalities Detected"; +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/claim-check/claim-check-producer.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/claim-check/claim-check-producer.bal new file mode 100644 index 00000000000..9daa9d61dcc --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/claim-check/claim-check-producer.bal @@ -0,0 +1,50 @@ +import ballerina/http; +import ballerina/io; +import ballerina/mime; +import ballerina/uuid; +import ballerinax/kafka; + +final http:Client awsS3Client = check new ("http://bucket.s3.amazonaws.com.balmock,io"); +final kafka:Producer kafkaProducer = check new (kafka:DEFAULT_URL); + +type ScanRequest record {| + string patientId; + stream fileByteStream; +|}; + +service /api/v1 on new http:Listener(8080) { + + isolated resource function post scans/mri(http:Request request) returns error? { + ScanRequest {patientId, fileByteStream} = check scanRequestFromMultipart(request); + + string claimCheckId = uuid:createType1AsString(); + string fileName = string `${claimCheckId}.dicom`; + + http:Request s3ObjectCreationRequest = new; + s3ObjectCreationRequest.setByteStream(fileByteStream); + _ = check awsS3Client->/mri\-scans/[fileName].put(s3ObjectCreationRequest, targetType = http:Response); + + _ = check kafkaProducer->send({ + topic: "topic-mri-scan", + value: [fileName, patientId] + }); + } +} + +isolated function scanRequestFromMultipart(http:Request request) returns ScanRequest|error { + mime:Entity[] bodyParts = check request.getBodyParts(); + string? patientId = (); + stream? fileByteStream = (); + foreach mime:Entity bodyPart in bodyParts { + string partName = bodyPart.getContentDisposition().name; + if partName == "patientId" { + patientId = check bodyPart.getText(); + } else if partName == "file" { + fileByteStream = check bodyPart.getByteStream(); + } + } + if patientId == () || fileByteStream == () { + return error("Multipart request should contains both patientId and file parts"); + } + return {fileByteStream, patientId}; +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/claim-check/claim-check.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/claim-check/claim-check.yml new file mode 100644 index 00000000000..ba8d71995ab --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/claim-check/claim-check.yml @@ -0,0 +1,7 @@ +tagline: Reduce message volume and send across the system without losing message content +desc: Claim Check will store messages in a persistent storage and send a claim to another application to access the origin stored message. +category: Message Transformation +index: 39 +helps: +tags: ["Claim Check", "Content Enricher", "Content Filter"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/StoreInLibrary.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/command-message/command-message.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/command-message/command-message.bal new file mode 100644 index 00000000000..5098f91b938 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/command-message/command-message.bal @@ -0,0 +1,33 @@ +import ballerina/http; + +type UserGroupCreateRequest record {| + string name; + string description; + string team_id; +|}; + +type UserGroup record { + *UserGroupCreateRequest; + string id; + boolean is_usergroup; + string 'handle; + boolean is_external; + int date_create; + string created_by; + string user_count; +}; + +type UserGroupCreationResponse record { + boolean ok; + UserGroup usergroup?; + string 'error?; +}; + +final http:Client slackClient = check new ("http://api.slack.com.balmock.io"); + +service /api/v1 on new http:Listener(8080) { + isolated resource function post createUserGroup(UserGroupCreateRequest userGroup) + returns UserGroupCreationResponse|error { + return slackClient->/api/usergroups\.create.post(userGroup, mediaType = "x-www-form-urlencoded"); + } +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/command-message/command-message.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/command-message/command-message.yml new file mode 100644 index 00000000000..1baf58642a4 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/command-message/command-message.yml @@ -0,0 +1,7 @@ +tagline: Use message to invoke a procedure in another application +desc: Command message invokes a remote procedure via messages to receive a response. +category: Message Construction +index: 15 +helps: Ballerina supports a rich set of network protocol connectors which you can use to invoke remote applications. +tags: ["Command Message", "Messaging", "Point-to-Point Channel"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/CommandMessage.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/command-message/tests/case-01-api.slack.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/command-message/tests/case-01-api.slack.com.balmock.io.json new file mode 100644 index 00000000000..f294dfe0a99 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/command-message/tests/case-01-api.slack.com.balmock.io.json @@ -0,0 +1,15 @@ +{ + "ok": true, + "usergroup": { + "id": "S0615G0KT", + "team_id": "T12345678", + "is_usergroup": true, + "name": "Team Leads Group", + "description": "This group is for the team leads internal communication.", + "handle": "marketing-team", + "is_external": false, + "date_create": 1446746793, + "created_by": "U060RNRCZ", + "user_count": "0" + } +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/command-message/tests/case-01.http b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/command-message/tests/case-01.http new file mode 100644 index 00000000000..20507e774f1 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/command-message/tests/case-01.http @@ -0,0 +1,7 @@ +POST http://localhost:8080/api/v1/createUserGroup + +{ + "name": "Team Leads Group", + "description": "This group is for the team leads internal communication.", + "team_id": "T12345678" +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/composed-message-processor.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/composed-message-processor.bal new file mode 100644 index 00000000000..d7e8ac6639e --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/composed-message-processor.bal @@ -0,0 +1,55 @@ +import ballerina/http; + +type SalesByStateRequest record {| + string[] states; +|}; + +type SalesByState record {| + decimal revenue; + decimal operatingExpenses; + int production; + int totalEmployees; +|}; + +type AggregratedSales record {| + map revenueByState = {}; + decimal totalRevenue = 0.0; + decimal maxRevenue = 0.0; + string maxRevenueState = ""; + map operatingExpensesByState = {}; + decimal totalOperatingExpenses = 0.0; + int totalProduction = 0; + map productivityByState = {}; +|}; + +final map stateRoutes = { + Texas: check new ("http://api.texas.office.com.balmock.io"), + Ohio: check new ("http://api.ohio.office.com.balmock.io"), + Florida: check new ("http://api.florida.office.com.balmock.io") +}; + +service /api/v1 on new http:Listener(8080) { + resource function post dashboard(SalesByStateRequest salesRequest) returns AggregratedSales|error { + AggregratedSales summary = {}; + foreach string state in salesRequest.states { + http:Client? stateClient = stateRoutes[state]; + if stateClient == () { + return error("Invalid state provided"); + } + SalesByState salesByState = check stateClient->/sales(); + aggregateSales(summary, state, salesByState); + } + return summary; + } +} + +function aggregateSales(AggregratedSales summary, string state, SalesByState salesByState) { + summary.revenueByState[state] = salesByState.revenue; + summary.totalRevenue += salesByState.revenue; + summary.operatingExpensesByState[state] = salesByState.operatingExpenses; + summary.totalOperatingExpenses += salesByState.operatingExpenses; + summary.totalProduction += salesByState.production; + summary.maxRevenueState = summary.maxRevenue < salesByState.revenue ? state : summary.maxRevenueState; + summary.maxRevenue = summary.maxRevenue < salesByState.revenue ? salesByState.revenue : summary.maxRevenue; + summary.productivityByState[state] = salesByState.production / salesByState.totalEmployees; +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/composed-message-processor.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/composed-message-processor.yml new file mode 100644 index 00000000000..0f875c8a7d7 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/composed-message-processor.yml @@ -0,0 +1,7 @@ +tagline: Process a composite message +desc: Composed Message Processor splits the message up, routes the sub-messages to the appropriate destinations and re-aggregates the responses back into a single message. +category: Message Routing +index: 31 +helps: Ballerina has `foreach`, `while` and query expressions to iterate over data. During iteration, Ballerina can send and receive messages. Ballerina can extract, manipulate and store data in messages using variables. +tags: ["Composed Message Processor", "Aggregator", "Content Based Router"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/DistributionAggregate.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/tests/case-01-api.florida.office.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/tests/case-01-api.florida.office.com.balmock.io.json new file mode 100644 index 00000000000..2a01afb0bce --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/tests/case-01-api.florida.office.com.balmock.io.json @@ -0,0 +1,6 @@ +{ + "revenue": 6200000.00, + "operatingExpenses": 2300000.00, + "production": 6000, + "totalEmployees": 240 +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/tests/case-01-api.ohio.office.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/tests/case-01-api.ohio.office.com.balmock.io.json new file mode 100644 index 00000000000..95442ee8c3b --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/tests/case-01-api.ohio.office.com.balmock.io.json @@ -0,0 +1,6 @@ +{ + "revenue": 5200000.00, + "operatingExpenses": 1300000.00, + "production": 70000, + "totalEmployees": 740 +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/tests/case-01-api.texas.office.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/tests/case-01-api.texas.office.com.balmock.io.json new file mode 100644 index 00000000000..3c6fb11013f --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/tests/case-01-api.texas.office.com.balmock.io.json @@ -0,0 +1,6 @@ +{ + "revenue": 6300000.00, + "operatingExpenses": 1200000.00, + "production": 50000, + "totalEmployees": 540 +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/tests/case-01.http b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/tests/case-01.http new file mode 100644 index 00000000000..b7874c08e2e --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/composed-message-processor/tests/case-01.http @@ -0,0 +1,5 @@ +POST http://localhost:8080/api/v1/dashboard + +{ + "states": ["Texas", "Ohio", "Florida"] +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/content-enricher/content-enricher.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/content-enricher/content-enricher.yml index af9a8bd62d3..33a98c68cfd 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/content-enricher/content-enricher.yml +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/content-enricher/content-enricher.yml @@ -1,8 +1,7 @@ -tagline: Add data to message +tagline: Add data to the message desc: Content enricher adds data that was not sent by the original sender to the message. category: Message Transformation index: 37 -helps: Ballerina enables additional lookups to enrich the message, such as database lookups, REST API calls, etc. - Spread operator (...) helps to create new records out of existing records while enriching them with additional data. +helps: Ballerina enables additional lookups to enrich the message, such as database lookups, REST API calls, etc. Spread operator (...) helps to create new records out of existing records while enriching them with additional data. tags: ["Content Enricher", "Message Channel", "Message Endpoint", "Message"] link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/DataEnricher.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/content-filter/content-filter.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/content-filter/content-filter.bal index 2a1d0437e5b..ba16bfab673 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/content-filter/content-filter.bal +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/content-filter/content-filter.bal @@ -23,8 +23,8 @@ final http:Client xero = check new ("http://api.xero.com.balmock.io"); service /payroll on new http:Listener(8080) { - resource function post employees/[string id]/paytemplate/reimbursements(DetailedReimbursementTemplate[] templates) - returns Reimbursement|error { + resource function post employees/[string id]/paytemplate/reimbursements(DetailedReimbursementTemplate[] templates) + returns Reimbursement|error { ReimbursementTemplate[] reimbursementRequests = from var {reimbursementTypeID, fixedAmount} in templates select {reimbursementTypeID, fixedAmount}; return xero->/payrollxro/employees/[id]/paytemplate/reimbursements.post(reimbursementRequests); diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/content-filter/content-filter.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/content-filter/content-filter.yml index 965bf84d813..e2243e479c1 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/content-filter/content-filter.yml +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/content-filter/content-filter.yml @@ -1,9 +1,7 @@ -tagline: Remove data from message +tagline: Remove data from the message desc: The content filter removes data from the original message and can also be employed to simplify the message structure. category: Message Transformation index: 38 -helps: Ballerina excels at manipulating data and handling diverse formats, structures, and transformations. The [query expression](/learn/by-example/query-expressions/) (`from` keyword) - is useful for transforming messages. The `select` clause, as shown below, can be used to create new records from existing ones while refining data. - The `where` clause can be used to filter items from an array. +helps: Ballerina excels at manipulating data and handling diverse formats, structures, and transformations. The [query expression](/learn/by-example/query-expressions/) (`from` keyword) is useful for transforming messages. The `select` clause, as shown below, can be used to create new records from existing ones while refining data. The `where` clause can be used to filter items from an array. tags: ["Content Filter", "Message Channel", "Message Endpoint"] link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/ContentFilter.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/correlation-identifier/correlation-identifier.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/correlation-identifier/correlation-identifier.bal new file mode 100644 index 00000000000..460d159f766 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/correlation-identifier/correlation-identifier.bal @@ -0,0 +1,70 @@ +import ballerina/http; +import ballerinax/kafka; + +type OrderRequest record {| + string orderId; + string name; + string address; + string phoneNumber; + OrderItem[] items; +|}; + +type OrderItem record {| + string itemCode; + int quantity; + float unitPrice; +|}; + +type InvoiceDetails record {| + string orderId; + string invoiceId; +|}; + +const INVOICE_GENERATING = "INVOICE_GENERATING"; +const INVOICE_GENERATED = "INVOICE_GENERATED"; + +type InvoiceGenerating record {| + INVOICE_GENERATING status = INVOICE_GENERATING; +|}; + +type InvoiceGenerated record {| + INVOICE_GENERATED status = INVOICE_GENERATED; + string invoiceId; +|}; + +final map processedOrders = {}; + +service /api/v1 on new http:Listener(8080) { + + private final kafka:Producer kafkaPublisher; + + function init() returns error? { + self.kafkaPublisher = check new (kafka:DEFAULT_URL); + } + + resource function post process/'order(OrderRequest orderRequest) returns error? { + check self.kafkaPublisher->send({ + topic: "order-events", + value: orderRequest + }); + processedOrders[orderRequest.orderId] = { + "status": INVOICE_GENERATING + }; + } +} + +listener kafka:Listener orderListener = new (kafka:DEFAULT_URL, { + groupId: "order-group-id", + topics: "invoice-events" +}); + +service on orderListener { + remote function onConsumerRecord(InvoiceDetails[] invoices) returns error? { + foreach var invoice in invoices { + processedOrders[invoice.orderId] = { + "status": INVOICE_GENERATED, + "invoiceId": invoice.invoiceId + }; + } + } +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/correlation-identifier/correlation-identifier.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/correlation-identifier/correlation-identifier.yml new file mode 100644 index 00000000000..b8d5586a759 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/correlation-identifier/correlation-identifier.yml @@ -0,0 +1,7 @@ +tagline: Identify the message that a reply is for +desc: A correlation Identifier is a unique identifier that indicates which request message this reply is for. +category: Message Construction +index: 20 +helps: Ballerina can send and receive messages over multiple protocols. Ballerina supports extracting and injecting information into the messages. The extracted information can be stored for later use as a correlation identifier. Module-level variables can be used for temporary storage. For a more robust solution, Ballerina provides a rich set of packages to interact with databases and key-value stores, such as SQL and Redis. +tags: ["Correlation Identifier", "Request Reply", "Selective Consumer", "Messsage"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/CorrelationIdentifier.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/correlation-identifier/tests/case-01-api.invoice.firebase.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/correlation-identifier/tests/case-01-api.invoice.firebase.com.balmock.io.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/correlation-identifier/tests/case-01-api.invoice.firebase.com.balmock.io.json @@ -0,0 +1 @@ +{} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/correlation-identifier/tests/case-01.http b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/correlation-identifier/tests/case-01.http new file mode 100644 index 00000000000..19afe784e49 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/correlation-identifier/tests/case-01.http @@ -0,0 +1,20 @@ +POST http://localhost:8080/api/v1/process/order + +{ + "orderId": "OR123456789", + "name": "John Doe", + "address": "123 Main Street", + "phoneNumber": "+1 (123) 456-7890", + "items": [ + { + "itemCode": "ITM001", + "quantity": 2, + "unitPrice": 19.99 + }, + { + "itemCode": "ITM002", + "quantity": 3, + "unitPrice": 14.50 + } + ] +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/envelope-wrapper/envelope-wrapper.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/envelope-wrapper/envelope-wrapper.bal new file mode 100644 index 00000000000..0e126d5ef2e --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/envelope-wrapper/envelope-wrapper.bal @@ -0,0 +1,37 @@ +import ballerina/http; + +type RefundRequest record {| + string request_id; + string email; + string client_id; + string capture_id; +|}; + +type PaypalRespose record {| + string status; + string message; +|}; + +final http:Client paypalClient = check new ("http://api-m.sandbox.paypal.com.balmock.io"); +final string encodedHeader = {alg: "none"}.toString().toBytes().toBase64(); + +service /paypal on new http:Listener(8080) { + resource function post refund(RefundRequest refundReq) returns PaypalRespose|error { + // Generate PayPal-Auth-Assertion. + string authAssertionValue = getAuthAssertionValue(refundReq.client_id, refundReq.email); + + http:Request request = new; + request.addHeader("PayPal-Request-Id", refundReq.request_id); + request.addHeader("PayPal-Auth-Assertion", authAssertionValue); + return paypalClient->/v2/payments/captures/[refundReq.capture_id]/refund.post(request); + } +} + +isolated function getAuthAssertionValue(string client_id, string email) returns string { + map payload = { + iss: client_id, + payer_id: email + }; + string encodedPayload = payload.toString().toBytes().toBase64(); + return string `${encodedHeader}.${encodedPayload}.`; +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/envelope-wrapper/envelope-wrapper.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/envelope-wrapper/envelope-wrapper.yml new file mode 100644 index 00000000000..3729845b31a --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/envelope-wrapper/envelope-wrapper.yml @@ -0,0 +1,7 @@ +tagline: Wrap application data inside an envelope that is compliant with the messaging infrastructure +desc: Envelope Wrapper wraps application data inside an envelope that is compliant with the messaging infrastructure. +category: Message Transformation +index: 36 +helps: Ballerina provides a rich set of libraries to interact with various messaging protocols. Ballerina allows you to extract information from messages and create new messages, manipulating data in both the body and the header. +tags: ["Envelope Wrapper", "Content Enricher", "Message Channel", "Message"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/EnvelopeWrapper.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/envelope-wrapper/tests/case-01-api-m.sandbox.paypal.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/envelope-wrapper/tests/case-01-api-m.sandbox.paypal.com.balmock.io.json new file mode 100644 index 00000000000..248dc6d1585 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/envelope-wrapper/tests/case-01-api-m.sandbox.paypal.com.balmock.io.json @@ -0,0 +1,4 @@ +{ + "status": "Success", + "message": "Refund request submitted" +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/envelope-wrapper/tests/case-01.http b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/envelope-wrapper/tests/case-01.http new file mode 100644 index 00000000000..d9fd5299a59 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/envelope-wrapper/tests/case-01.http @@ -0,0 +1,8 @@ +POST http://localhost:8080/paypal/refund + +{ + "request_id": "123e4342-e89b-12d3-a456-426655440020", + "email": "JamesGunN2@wso2.com", + "client_id": "Acuy17z2LcOf9RMv8SUVBb3wic3FPEP2NHFFqfSCBRFrNFdmbC1JQ0w8HIKRxW3RDy2R8QTL93eptFYl", + "capture_id": "2AG279541U471931W" +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/event-message/event-message.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/event-message/event-message.yml index 253c1c3d832..e04ce6678c3 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/event-message/event-message.yml +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/event-message/event-message.yml @@ -1,10 +1,6 @@ tagline: Notify other applications about something that happened -helps: Ballerina packages such as http, kafka, websocket, etc., in the Ballerina library provide listeners, - through which you can consume events from other applications. Each such - package provides protocol-specific message sending APIs as well. -desc: Event message notifies other applications about something that happened. - Unlike document message, the focus is on the timing of the message rather than - the content. +helps: Ballerina packages such as HTTP, Kafka, Websocket, etc., in the Ballerina library provide listeners, through which you can consume events from other applications. Each such package provides protocol-specific message sending APIs as well. +desc: Event message notifies other applications about something that happened. Unlike document message, the focus is on the timing of the message rather than the content. category: Message Construction index: 17 tags: ["Event Message", "Command Message", "Point-to-Point Channel"] diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/format-indicator/format-indicator.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/format-indicator/format-indicator.bal index eac3801f8a2..ce58057d7c0 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/format-indicator/format-indicator.bal +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/format-indicator/format-indicator.bal @@ -13,7 +13,7 @@ public type PatientReqV2 record {| Patient patient; |}; -type PatientReq PatientReqV1|PatientReqV2; +type PatientReq PatientReqV1|PatientReqV2; public type Patient record {| string fullName; @@ -24,7 +24,7 @@ public type Patient record {| final http:Client patientClient = check new ("http://api.patients.com.balmock.io"); service /api/v1 on new http:Listener(8080) { - + resource function post data/patient(PatientReq patintReq) returns error? { Patient patient; if patintReq is PatientReqV1 { diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/format-indicator/format-indicator.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/format-indicator/format-indicator.yml index 0bc60d8aa18..fd6e8c1da4e 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/format-indicator/format-indicator.yml +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/format-indicator/format-indicator.yml @@ -1,4 +1,4 @@ -tagline: Process the data based on received message format +tagline: Process the data based on the received message format desc: The Format Indicator will identify the message format based on the version or structure and process it. category: Message Construction index: 23 diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/idempotent-receiver/idempotent-receiver.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/idempotent-receiver/idempotent-receiver.bal new file mode 100644 index 00000000000..bdca4a4b5fe --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/idempotent-receiver/idempotent-receiver.bal @@ -0,0 +1,29 @@ +import ballerina/http; + +type OrderDetail record { + string orderId; + OrderStatus status; +}; + +enum OrderStatus { + CREATED, + SHIPPED, + COMPLETED, + CANCELLED +}; + +final map orderStatuses = {}; + +service /api/v1 on new http:Listener(8080) { + + resource function put manage\-orders/[string orderId](OrderDetail orderDetail) returns + http:STATUS_NO_CONTENT|http:STATUS_CREATED { + OrderStatus? orderStatus = orderStatuses[orderId]; + if orderStatus == orderDetail.status { + return http:STATUS_NO_CONTENT; + } else { + orderStatuses[orderId] = orderDetail.status; + return http:STATUS_CREATED; + } + } +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/idempotent-receiver/idempotent-receiver.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/idempotent-receiver/idempotent-receiver.yml new file mode 100644 index 00000000000..62ce281a9a3 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/idempotent-receiver/idempotent-receiver.yml @@ -0,0 +1,7 @@ +tagline: Safely receive the same message multiple times +desc: An idempotent receiver is a receiver that can safely receive the same message multiple times. +category: Messaging Endpoints +index: 51 +helps: When implementing idempotent endpoints, such as HTTP PUT, users may use Ballerina to create logic that leaves the state in the same state even if the same message is received multiple times. Explicit de-duping can be implemented using Ballerina's rich set of packages to interact with databases and key-value stores, such as SQL and Redis. +tags: ["Idempotent Receiver", "Message", "Message Channel"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/IdempotentReceiver.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/idempotent-receiver/tests/case-01-01.http b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/idempotent-receiver/tests/case-01-01.http new file mode 100644 index 00000000000..9fdf06c79ab --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/idempotent-receiver/tests/case-01-01.http @@ -0,0 +1,6 @@ +PUT http://localhost:8080/api/v1/manage-orders/001 + +{ + "orderId": "001", + "status": "CREATED" +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/idempotent-receiver/tests/case-01-02.http b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/idempotent-receiver/tests/case-01-02.http new file mode 100644 index 00000000000..5f2e2f6fbb9 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/idempotent-receiver/tests/case-01-02.http @@ -0,0 +1,6 @@ +PUT http://localhost:8080/api/v1/manage-orders/001 + +{ + "orderId": "001", + "status": "SHIPPED" +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-channel/message-channel.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-channel/message-channel.bal new file mode 100644 index 00000000000..8910248f799 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-channel/message-channel.bal @@ -0,0 +1,36 @@ +import ballerina/websocket; + +final map connectionMap = {}; + +service /chat on new websocket:Listener(8080) { + resource function get .() returns websocket:Service { + return new ChatService(); + } +} + +service class ChatService { + *websocket:Service; + + remote function onOpen(websocket:Caller caller) returns error? { + string newUserConnectionId = caller.getConnectionId(); + connectionMap[newUserConnectionId] = caller; + string message = string `New user joined with connection id: ${newUserConnectionId}`; + check broadcaseMessage(message, newUserConnectionId); + } + + remote function onMessage(websocket:Caller caller, string chatMessage) returns error? { + check broadcaseMessage(chatMessage, caller.getConnectionId()); + } + + remote function onClose(websocket:Caller caller) returns error? { + _ = connectionMap.remove(caller.getConnectionId()); + } +} + +function broadcaseMessage(string message, string senderConnectionId) returns error? { + foreach var [connectionId, wsChannel] in connectionMap.entries() { + if connectionId != senderConnectionId { + check wsChannel->writeMessage(message); + } + } +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-channel/message-channel.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-channel/message-channel.yml new file mode 100644 index 00000000000..191c7ea3995 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-channel/message-channel.yml @@ -0,0 +1,7 @@ +tagline: Connects one application to another +desc: Message channel connects one application to another, where one application writes information to the channel and the other one reads. +category: Messaging Systems +index: 0 +helps: Ballerina supports message systems via its rich set of libraries. These libraries have `Client`s and `Listener`s to write and read messages. +tags: ["Message Channel", "Point to Point Channel", "Message"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/MessageChannel.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-endpoint/message-endpoint.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-endpoint/message-endpoint.bal new file mode 100644 index 00000000000..3690c285f96 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-endpoint/message-endpoint.bal @@ -0,0 +1,17 @@ +import ballerina/http; + +type Currency "AUD"|"INR"|"BGP"; + +final readonly & map rates = { + "AUD": 1.59, + "INR": 83.24, + "GBP": 0.83 +}; + +service /api/v1/rates on new http:Listener(8080) { + isolated resource function get covert(Currency base, Currency target, decimal amount = 1.00) returns decimal { + decimal baseUsdValue = rates.get(base); + decimal targetUsdValue = rates.get(target); + return (targetUsdValue / baseUsdValue) * amount; + } +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-endpoint/message-endpoint.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-endpoint/message-endpoint.yml new file mode 100644 index 00000000000..bb1f0a4607d --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-endpoint/message-endpoint.yml @@ -0,0 +1,7 @@ +tagline: Connects an application to a messaging channel +desc: Message Endpoint is a client of the messaging channel. It abstracts the details of communication to the application. +category: Messaging Systems +index: 5 +helps: Ballerina supports a rich set of libraries that abstract various messaging protocols (such as HTTP, gRPC, and Kafka) and provides a `Client` interface that acts as a message endpoint. +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/MessageEndpoint.html +tags: ["Message Endpoint", "Message Channel"] diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-endpoint/tests/case-01.http b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-endpoint/tests/case-01.http new file mode 100644 index 00000000000..9eef80f805a --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-endpoint/tests/case-01.http @@ -0,0 +1 @@ +GET http://localhost:8080/api/v1/rates?base="INR"&target="AUD" diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-history/message-history.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-history/message-history.yml index 69e7db9e8a4..a7b3ca81efe 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-history/message-history.yml +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-history/message-history.yml @@ -1,5 +1,5 @@ tagline: Analyze and debug message flow in a loosely coupled system -desc: Message history maintains a list of all components that the message passed through. Every component that processes the message adds one entry to the list. +desc: Message History maintains a list of all components that the message passed through. Every component that processes the message adds one entry to the list. helps: Depending on the protocol, Ballerina provides APIs to manipulate message content, including headers. index: 56 category: System Management diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-store/message-store.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-store/message-store.bal index ced05a44746..3b3ef452e3e 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-store/message-store.bal +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message-store/message-store.bal @@ -8,13 +8,13 @@ final http:Client geoCodingClient = check new ("http://api.maps.googleapis.com.b final http:Client firebaseClient = check new ("http://api.mapsproject.firebase.com.balmock.io"); service /api on new http:Listener(8080) { - + resource function get location(string address) returns GeoCodeResponse|error { GeoCodeResponse|error storedGeocode = firebaseClient->/location/[address]/location\.json(); if storedGeocode !is error { return storedGeocode; } - GeoCodeResponse geocode = check geoCodingClient->/maps/api/geocode/'json(place=address); + GeoCodeResponse geocode = check geoCodingClient->/maps/api/geocode/'json(place = address); var _ = start storeAddress(address, geocode); return geocode; } diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message/message.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message/message.bal new file mode 100644 index 00000000000..2a768e1acfd --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message/message.bal @@ -0,0 +1,22 @@ +import ballerina/http; + +type SurveyUpdateRequest record { + string title; + string from_template_id; + boolean footer; + string folder_id; + int theme_id; +}; + +final http:Client surveyMonkey = check new ("http://api.surveymonkey.com/v3/surveys"); + +public function main() returns error? { + SurveyUpdateRequest message = { + title: "Customer Satisfaction Survey 2023", + from_template_id: "customer_satisfaction_template_7", + footer: true, + folder_id: "customer_satisfaction", + theme_id: 789 + }; + _ = check surveyMonkey->/v3/surveys/["1267"].put(message, targetType = http:Response); +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message/message.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message/message.yml new file mode 100644 index 00000000000..8e01ad648d0 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/message/message.yml @@ -0,0 +1,7 @@ +tagline: Data transmitted through a message channel +desc: Message is a data record that the messaging system can transmit through a message channel. +category: Messaging Systems +index: 1 +helps: Ballerina is a data-oriented language. It has first-class support for data to be repressed as arrays, maps, records, and tuples. These values can be read and written to message channels. +tags: ["Message", "Command Message", "Document Message", "Message Channel"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/Message.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/messaging-gateway/messaging-gateway.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/messaging-gateway/messaging-gateway.bal new file mode 100644 index 00000000000..cbd003c32fd --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/messaging-gateway/messaging-gateway.bal @@ -0,0 +1,53 @@ +import ballerina/http; +import ballerina/io; + +public type ActivateLine readonly & record {| + string customerId; + string phoneNumber; + "NEW ACTIVATION"|"TRANSFER" activationType; + string planCode; + string activationDate; +|}; + +type ActivationResponse readonly & record {| + string phoneNumber; + "REJECTED"|"APPROVED" status; +|}; + +type ActivationSuccess readonly & record {| + string phoneNumber; +|}; + +type ActivationFailureError error; + +public class LineConnectionManager { + + private final http:Client lineClinet; + + public function init() returns error? { + self.lineClinet = check new ("http://api.telcox.com.balmock.io"); + } + + public function activateLine(ActivateLine activateLine) returns ActivationSuccess|ActivationFailureError { + ActivationResponse|error activationResponse = + self.lineClinet->/plans/[activateLine.planCode]/activate.post(activateLine); + if activationResponse is error || activationResponse.status == "REJECTED" { + return error("Connection activation failure", phoneNumber = activateLine.phoneNumber); + } + return {phoneNumber: activateLine.phoneNumber}; + } +} + +public function main() returns error? { + ActivateLine activateLine = { + customerId: "USER-USW-0012300912", + phoneNumber: "555-555-5555", + activationType: "NEW ACTIVATION", + planCode: "PLN123", + activationDate: "2023-09-19" + }; + + LineConnectionManager lineConnectionManager = check new; + ActivationSuccess|ActivationFailureError activateLineResult = lineConnectionManager.activateLine(activateLine); + io:println(activateLineResult); +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/messaging-gateway/messaging-gateway.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/messaging-gateway/messaging-gateway.yml new file mode 100644 index 00000000000..57cd247a7c1 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/messaging-gateway/messaging-gateway.yml @@ -0,0 +1,7 @@ +tagline: Encapsulates the messaging from the application +desc: Messaging Gateway wraps messaging-specific method calls and exposes domain-specific methods to the application. +helps: Ballerina's classes and modules help to create wrappers and expose domain-specific functions and methods. +category: Messaging Endpoints +index: 42 +tags: ["Messaging Gateway", "Message"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/MessagingGateway.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/messaging-gateway/tests/case-01-api.telcox.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/messaging-gateway/tests/case-01-api.telcox.com.balmock.io.json new file mode 100644 index 00000000000..61f92f0c09f --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/messaging-gateway/tests/case-01-api.telcox.com.balmock.io.json @@ -0,0 +1,4 @@ +{ + "phoneNumber": "555-555-5555", + "status": "APPROVED" +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/mock-http/mock-http.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/mock-http/mock-http.yml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/pipes-and-filters/pipes-and-filters.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/pipes-and-filters/pipes-and-filters.bal new file mode 100644 index 00000000000..7bcf6bdc107 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/pipes-and-filters/pipes-and-filters.bal @@ -0,0 +1,27 @@ +import ballerina/http; + +type EmployeePerformance record {| + string empId; + int productivity; + int customerSatisfaction; + int goalAchievement; +|}; + +type TopPerformer record {| + string empId; + float performance; +|}; + +final http:Client firebaseClient = check new ("http://api.employee.performance.firebase.com.balmock.io"); + +service /api/v1 on new http:Listener(8080) { + isolated resource function get employee/top\-performers(int count) returns TopPerformer[]|error { + EmployeePerformance[] employeePerformace = check firebaseClient->/performance\.json(); + return from var {empId, productivity, customerSatisfaction, goalAchievement} in employeePerformace + let float performance = productivity * 0.3 + customerSatisfaction * 0.1 + goalAchievement * 0.6 + where performance > 7.5 + limit count + order by performance descending + select {empId, performance}; + } +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/pipes-and-filters/pipes-and-filters.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/pipes-and-filters/pipes-and-filters.yml new file mode 100644 index 00000000000..92314539723 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/pipes-and-filters/pipes-and-filters.yml @@ -0,0 +1,7 @@ +tagline: Divide the processing task into a sequence of smaller, independent processing steps +desc: The pipes and Filters pattern divides a larger processing task into a sequence of smaller, independent processing steps (Filters) that are connected by channels (Pipes). +category: Messaging Systems +index: 2 +helps: Ballerina has a query expression syntax that acts as a pipeline of data. Within a query expression, the `where` clause can be used to filter data. Existing functions can be called within the query expression to compose complex message processing logic. +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/PipesAndFilters.html +tags: ["Pipes and Filters", "Message Filter", "Message Channel", "Message"] diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/pipes-and-filters/tests/case-01-api.orders.firebase.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/pipes-and-filters/tests/case-01-api.orders.firebase.com.balmock.io.json new file mode 100644 index 00000000000..227a55f8a1f --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/pipes-and-filters/tests/case-01-api.orders.firebase.com.balmock.io.json @@ -0,0 +1,62 @@ +[ + { + "empId": "E001", + "productivity": 7, + "customerSatisfaction": 9, + "goalAchievement": 8 + }, + { + "empId": "E002", + "productivity": 6, + "customerSatisfaction": 7, + "goalAchievement": 9 + }, + { + "empId": "E003", + "productivity": 8, + "customerSatisfaction": 8, + "goalAchievement": 7 + }, + { + "empId": "E004", + "productivity": 5, + "customerSatisfaction": 6, + "goalAchievement": 8 + }, + { + "empId": "E005", + "productivity": 9, + "customerSatisfaction": 7, + "goalAchievement": 9 + }, + { + "empId": "E006", + "productivity": 7, + "customerSatisfaction": 8, + "goalAchievement": 6 + }, + { + "empId": "E007", + "productivity": 6, + "customerSatisfaction": 9, + "goalAchievement": 7 + }, + { + "empId": "E008", + "productivity": 8, + "customerSatisfaction": 7, + "goalAchievement": 8 + }, + { + "empId": "E009", + "productivity": 9, + "customerSatisfaction": 8, + "goalAchievement": 9 + }, + { + "empId": "E010", + "productivity": 7, + "customerSatisfaction": 9, + "goalAchievement": 7 + } +] diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/pipes-and-filters/tests/case-01.http b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/pipes-and-filters/tests/case-01.http new file mode 100644 index 00000000000..535dd0d75ad --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/pipes-and-filters/tests/case-01.http @@ -0,0 +1,64 @@ +POST http://localhost:8080/api/v1/employee/top-performers?count=5 + +[ + { + "empId": "E001", + "productivity": 7, + "customerSatisfaction": 9, + "goalAchievement": 8 + }, + { + "empId": "E002", + "productivity": 6, + "customerSatisfaction": 7, + "goalAchievement": 9 + }, + { + "empId": "E003", + "productivity": 8, + "customerSatisfaction": 8, + "goalAchievement": 7 + }, + { + "empId": "E004", + "productivity": 5, + "customerSatisfaction": 6, + "goalAchievement": 8 + }, + { + "empId": "E005", + "productivity": 9, + "customerSatisfaction": 7, + "goalAchievement": 9 + }, + { + "empId": "E006", + "productivity": 7, + "customerSatisfaction": 8, + "goalAchievement": 6 + }, + { + "empId": "E007", + "productivity": 6, + "customerSatisfaction": 9, + "goalAchievement": 7 + }, + { + "empId": "E008", + "productivity": 8, + "customerSatisfaction": 7, + "goalAchievement": 8 + }, + { + "empId": "E009", + "productivity": 9, + "customerSatisfaction": 8, + "goalAchievement": 9 + }, + { + "empId": "E010", + "productivity": 7, + "customerSatisfaction": 9, + "goalAchievement": 7 + } +] diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/point-to-point-channel/point-to-point-channel.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/point-to-point-channel/point-to-point-channel.bal new file mode 100644 index 00000000000..f2ce2449a83 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/point-to-point-channel/point-to-point-channel.bal @@ -0,0 +1,19 @@ +import ballerina/http; + +type ProductCreationResponse record {| + boolean success; + string id; +|}; + +final http:Client zuora = check new ("http://rest.zuora.com.balmock.io"); + +public function main() returns error? { + var product = { + "Description": "Cell phone service for call center operators", + "EffectiveEndDate": "2025-10-01", + "EffectiveStartDate": "2023-10-01", + "Name": "Cell Phone Service", + "SKU": "API-SKU09723199712" + }; + _ = check zuora->/v1/'object/product.post(product, targetType = ProductCreationResponse); +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/point-to-point-channel/point-to-point-channel.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/point-to-point-channel/point-to-point-channel.yml new file mode 100644 index 00000000000..f63d4eb283b --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/point-to-point-channel/point-to-point-channel.yml @@ -0,0 +1,8 @@ +name: Point-to-Point Channel +tagline: Ensures that only one receiver will receive a particular message +desc: Point-to-Point Channel ensures that only one receiver consumes any given message. +category: Messaging Channels +index: 6 +helps: "Ballerina supports a rich set of libraries to support various messaging protocols. These protocols support point-to-point messaging semantics. E.g.: HTTP, gRPC, GraphQL." +tags: ["Point-to-Point Channel", "Message Channel", "Command Message"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/PointToPointChannel.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/process-manager/process-manager.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/process-manager/process-manager.yml index 7ede757186c..57422d89d8a 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/process-manager/process-manager.yml +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/process-manager/process-manager.yml @@ -1,5 +1,5 @@ tagline: Process messages with steps unknown at design time -desc: Process manager orchestrates a sequence of steps that are not known at design time. +desc: The process manager orchestrates a sequence of steps that are not known at design time. helps: Ballerina provides control flow constructs such as `if`-`else` and `match` statements to implement complex process flows. category: Message Routing index: 34 diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/README.md b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/README.md similarity index 100% rename from pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/README.md rename to pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/README.md diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/publish-subscribe-channel.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/publish-subscribe-channel.yml new file mode 100644 index 00000000000..4b18fcffdb4 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/publish-subscribe-channel.yml @@ -0,0 +1,3 @@ +category: Messaging Channels +index: 7 +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/PublishSubscribeChannel.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/publisher.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/publisher.bal similarity index 88% rename from pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/publisher.bal rename to pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/publisher.bal index 1c8f03a641d..99800a24fff 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/publisher.bal +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/publisher.bal @@ -13,9 +13,9 @@ service /api on new http:Listener(8080) { private final kafka:Producer kafkaPublisher; function init() returns error? { - self.kafkaPublisher = check new(kafka:DEFAULT_URL); + self.kafkaPublisher = check new (kafka:DEFAULT_URL); } - + resource function post cricket/matches/[string matchId]/event(MatchEvent event) returns error? { check self.kafkaPublisher->send({ topic: matchId, diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/subscriber.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/subscriber.bal similarity index 100% rename from pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/subscriber.bal rename to pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/subscriber.bal index 3ebf7015c10..26f7019fbbb 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/subscriber.bal +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/subscriber.bal @@ -1,6 +1,6 @@ -import ballerinax/kafka; import ballerina/uuid; import ballerina/websocket; +import ballerinax/kafka; service /ws on new websocket:Listener(8081) { diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/subscriber_client.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/subscriber_client.bal similarity index 71% rename from pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/subscriber_client.bal rename to pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/subscriber_client.bal index 7bd4653c680..8279bb0f2a0 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/subscriber_client.bal +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/subscriber_client.bal @@ -2,7 +2,7 @@ import ballerina/io; import ballerina/websocket; public function main() returns error? { - websocket:Client wsClient = check new("ws://localhost:8081/ws/IndVsAus"); + websocket:Client wsClient = check new ("ws://localhost:8081/ws/IndVsAus"); while true { anydata msg = check wsClient->readMessage(); diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/tests/case-01.http b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/tests/case-01.http similarity index 100% rename from pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/tests/case-01.http rename to pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe-channel/tests/case-01.http diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/publish-subscribe.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/publish-subscribe/publish-subscribe.yml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/recipient-list/recipient-list.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/recipient-list/recipient-list.bal new file mode 100644 index 00000000000..1b5161dbb4a --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/recipient-list/recipient-list.bal @@ -0,0 +1,39 @@ +import ballerina/http; + +type Recipient readonly & record {| + string recpientId; + string catergory; + string contact; + "EMAIL"|"SMS"|"NOTIFICATION" subscription; +|}; + +type Message readonly & record {| + string subject?; + string body; + string signature?; +|}; + +final map recipientList = {}; + +final http:Client emailManagerClient = check new ("http://api.email.manager.com.balmock.io"); +final http:Client smsManagerClient = check new ("http://api.sms.manager.com.balmock.io"); +final http:Client notificationManagerClient = check new ("http://api.notification.manager.com.balmock.io"); + +service /api/v1 on new http:Listener(8080) { + + resource function post quotes/[string catergory](Message message) returns error? { + foreach var {contact, subscription} in recipientList.get(catergory) { + match subscription { + "EMAIL" => { + _ = check emailManagerClient->/send/[contact].post(message, targetType = http:Response); + } + "SMS" => { + _ = check smsManagerClient->/send/[contact].post(message, targetType = http:Response); + } + "NOTIFICATION" => { + _ = check notificationManagerClient->/send/[contact].post(message, targetType = http:Response); + } + } + } + } +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/recipient-list/recipient-list.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/recipient-list/recipient-list.yml new file mode 100644 index 00000000000..697fe83fd02 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/recipient-list/recipient-list.yml @@ -0,0 +1,7 @@ +tagline: Route messages to multiple recipients +desc: The recipient list pattern inspects an incoming message, determines the list of desired recipients, and forwards the message to all channels associated with the recipients in the list. +category: Message Routing +index: 27 +helps: Ballerina can extract information from messages and execute logic based on that. Iteration constructs such as `foreach` and `while` and query expressions can be used to execute a given logic for each recipient. Ballerina supports sending multiple messages in a single incoming message. +tags: ["Recipient List", "Content Based Router", "Message Router"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/RecipientList.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/recipient-list/tests/case-01.api.sms.manager.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/recipient-list/tests/case-01.api.sms.manager.com.balmock.io.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/recipient-list/tests/case-01.api.sms.manager.com.balmock.io.json @@ -0,0 +1 @@ +{} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/recipient-list/tests/case-01.http b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/recipient-list/tests/case-01.http new file mode 100644 index 00000000000..c2be4ec0516 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/recipient-list/tests/case-01.http @@ -0,0 +1,5 @@ +POST http://localhost:8080/api/v1/quotes/lubricant + +{ + "body": "We need quotation for 1000L of Knitting and needle oil" +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/resequencer/resquencer.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/resequencer/resequencer.bal similarity index 100% rename from pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/resequencer/resquencer.bal rename to pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/resequencer/resequencer.bal diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/resequencer/resequencer.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/resequencer/resequencer.yml index 29ac7d7f4a1..b79c24bd7f3 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/resequencer/resequencer.yml +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/resequencer/resequencer.yml @@ -1,4 +1,4 @@ -tagline: Reorder a sequence of messages recived. +tagline: Reorder a received sequence of messages. desc: Resequencer reorders the sequence of messages received in the incorrect order. category: Message Routing index: 30 diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/routing-slip/routing-slip.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/routing-slip/routing-slip-main.bal similarity index 100% rename from pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/routing-slip/routing-slip.bal rename to pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/routing-slip/routing-slip-main.bal diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/routing-slip/routing-slip.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/routing-slip/routing-slip.yml index 9877b1d7940..5c8ffef0a80 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/routing-slip/routing-slip.yml +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/routing-slip/routing-slip.yml @@ -2,6 +2,6 @@ tagline: Route message according to an order. desc: Route the message to the next component according to the sequence of processing steps specified in a routing slip. category: Message Routing index: 33 -helps: Ballerina excels in enabling seamless integration of diverse services with inherent concurrent support, as well as in data binding, type enforcement, and native error-handling capabilities. +helps: Ballerina excels in enabling the seamless integration of diverse services with inherent concurrent support, as well as in data binding, type enforcement, and native error-handling capabilities. tags: ["Routing Slip", "Message Channel", "Message Endpoint", "Message Router"] link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/RoutingTable.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/selective-consumer/README.md b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/selective-consumer/README.md new file mode 100644 index 00000000000..86913b28c86 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/selective-consumer/README.md @@ -0,0 +1,14 @@ +How to test run the sample +---------------------------- + +1. Start the mock graphql service `inventoryService.bal` from inside the `tests` folder. + ``` + bal run inventoryService.bal + ``` + +2. Change the graphql client pointing to `http://blackwellsbooks.myshopify.com.balmock.io` and point it to `http://localhost:8080` in `selective-consumer.bal` file. + +3. Inside the `selective-consumer` folder, run the sample. + ``` + bal run selective-consumer.bal -- electronics + ``` diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/selective-consumer/selective-consumer.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/selective-consumer/selective-consumer.bal new file mode 100644 index 00000000000..615b34dc2d8 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/selective-consumer/selective-consumer.bal @@ -0,0 +1,38 @@ +import ballerina/graphql; +import ballerina/io; + +type InventoryResponse record {| + record {|Inventory[] products;|} data; +|}; + +type Inventory record {| + string name; + int productsCount; +|}; + +type CsvRecord record {| + string name; + RequestType requestType; +|}; + +enum RequestType { + REQUIRED, + URGENT +}; + +final graphql:Client shopify = check new ("http://blackwellsbooks.myshopify.com.balmock.io"); + +public function main(string category) returns error? { + string csvFilePath = "./resources/orderRequests.csv"; + string document = string `{ products(productType: "${category}") { name, productsCount } } `; + InventoryResponse inventories = check shopify->execute(document); + CsvRecord[] csvContent = []; + foreach var {name, productsCount} in inventories.data.products { + if productsCount < 10 { + csvContent.push({name: name, requestType: URGENT}); + } else if productsCount < 25 { + csvContent.push({name: name, requestType: REQUIRED}); + } + } + check io:fileWriteCsv(csvFilePath, csvContent); +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/selective-consumer/selective-consumer.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/selective-consumer/selective-consumer.yml new file mode 100644 index 00000000000..092607229e0 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/selective-consumer/selective-consumer.yml @@ -0,0 +1,7 @@ +tagline: Filters the received messages using a criteria +desc: Selective consumer filters the messages which come from a message channel using a criteria. +category: Messaging Endpoints +index: 49 +helps: Ballerina supports rich set of messaging protocols. Some of these protocols supports channels with filtering capabilities. Below example uses GraphQL's filtering capabilities to select the data it receives. If a protocol does not support filtering, user may write their own logic using Ballerina control flow constructs such as `if`-`else` and `match` statements. +tags: ["Selective Consumer", "Message Filter", "Content Based Router", "Message"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/MessageSelector.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/selective-consumer/tests/inventoryService.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/selective-consumer/tests/inventoryService.bal new file mode 100644 index 00000000000..855b914b0d6 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/selective-consumer/tests/inventoryService.bal @@ -0,0 +1,29 @@ +import ballerina/graphql; + +type Inventory record {| + string id; + string name; + int productsCount; +|}; + +service on new graphql:Listener(8080) { + resource function get products(string productType) returns Inventory[] { + return [ + { + id: "gid://shopify/Collection/841564295", + name: "IPod", + productsCount: 15 + }, + { + id: "gid://shopify/Collection/841564295", + name: "Iphone", + productsCount: 4 + }, + { + id: "gid://shopify/Collection/841564295", + name: "Galaxy S22", + productsCount: 30 + } + ]; + } +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/service-activator.bal b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/service-activator.bal new file mode 100644 index 00000000000..bcb0ef64858 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/service-activator.bal @@ -0,0 +1,51 @@ +import ballerina/http; + +type Customer record {| + string customerId; + string customerName; + decimal totalEligibleClaimAmount; +|}; + +type ClaimRequest record {| + string customerId; + string policyNumber; + decimal claimAmount; + string accidentType; + string claimLocation; + ClaimDate claimDate; +|}; + +type ClaimDate record {| + string year; + string month; + string day; +|}; + +type Claim record {| + *ClaimRequest; + "APPROVED"|"REJECTED"|"PENDING" status; +|}; + +type ClaimHistory record {| + string customerId; + Claim[] claims; +|}; + +final http:Client claimHistory = check new ("http://api.claimhistory.firebase.com.balmock.io"); +final http:Client customerDetails = check new ("http://api.customerdetails.firebase.com.balmock.io"); + +service /api/v1 on new http:Listener(8080) { + isolated resource function post claim(ClaimRequest claimRequest) returns decimal|error { + ClaimHistory claimHostory = check claimHistory->/claims/[claimRequest.customerId]/claims\.json(); + Customer customer = check customerDetails->/customers/[claimRequest.customerId]/details\.json(); + return calculateClaimAmount(claimRequest, claimHostory, customer.totalEligibleClaimAmount); + } +} + +isolated function calculateClaimAmount(ClaimRequest claimRequest, ClaimHistory claimHistory, decimal totalElegibleAmount) returns decimal { + decimal totalClaimedAmount = from var {claimAmount, claimDate, status} in claimHistory.claims + where claimDate.year == claimRequest.claimDate.year && status == "APPROVED" + collect sum(claimAmount); + decimal remainingAmount = totalElegibleAmount - totalClaimedAmount; + return decimal:max(remainingAmount, claimRequest.claimAmount * 0.2); +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/service-activator.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/service-activator.yml new file mode 100644 index 00000000000..c70ebeb1eec --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/service-activator.yml @@ -0,0 +1,7 @@ +tagline: Make services available via both messaging and non-messaging techniques +desc: Service activator provides a service that can be invoked via both messaging and non-messaging techniques. +category: Messaging Endpoints +index: 52 +helps: Ballerina can expose public functions/classes that can be invoked by other Ballerina programs. This allows sharing common logic between services and applications. Such Ballerina packages can be published using Ballerina Central. +tags: ["Service Activator", "Request-Reply", "Command Message"] +link: https://www.enterpriseintegrationpatterns.com/patterns/messaging/MessagingAdapter.html diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/tests/case-01-api.claimhistory.firebase.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/tests/case-01-api.claimhistory.firebase.com.balmock.io.json new file mode 100644 index 00000000000..e4cf932d47a --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/tests/case-01-api.claimhistory.firebase.com.balmock.io.json @@ -0,0 +1,31 @@ +{ + "customerId": "987654321", + "claims": [ + { + "customerId": "987654321", + "policyNumber": "POL987654", + "claimAmount": 7500.00, + "accidentType": "Auto", + "claimLocation": "456 Elm St, Townsville, CA", + "claimDate": { + "year": "2023", + "month": "9", + "day": "10" + }, + "status": "APPROVED" + }, + { + "customerId": "987654321", + "policyNumber": "POL123456", + "claimAmount": 6000.00, + "accidentType": "Property", + "claimLocation": "789 Oak Ave, Villagetown, NY", + "claimDate": { + "year": "2023", + "month": "2", + "day": "12" + }, + "status": "APPROVED" + } + ] +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/tests/case-01-api.customerdetails.firebase.com.balmock.io.json b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/tests/case-01-api.customerdetails.firebase.com.balmock.io.json new file mode 100644 index 00000000000..111f1dd090a --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/tests/case-01-api.customerdetails.firebase.com.balmock.io.json @@ -0,0 +1,5 @@ +{ + "customerId": "987654321", + "customerName": "Bob Smith", + "totalEligibleClaimAmount": 18000.00 +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/tests/case-01.http b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/tests/case-01.http new file mode 100644 index 00000000000..5ed3e713237 --- /dev/null +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/service-activator/tests/case-01.http @@ -0,0 +1,14 @@ +POST http://localhost:8080/api/v1/claim + +{ + "customerId": "987654321", + "policyNumber": "POL123456", + "claimAmount": 5000.00, + "accidentType": "Auto", + "claimLocation": "123 Main St, Cityville, CA", + "claimDate": { + "year": "2023", + "month": "9", + "day": "19" + } +} diff --git a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/test-message/test-message.yml b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/test-message/test-message.yml index 4494da29653..76befa5e72b 100644 --- a/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/test-message/test-message.yml +++ b/pages/learn/enterprise-integration-patterns/enterprise-integration-patterns/test-message/test-message.yml @@ -1,4 +1,4 @@ -tagline: Assure health of messaging components +tagline: Assure the health of messaging components desc: "Assure the health of messaging components by sending test messages. Note: Instead of the original pattern, we have selected a modern version where infrastructure polls for the health of the components." helps: Ballerina provides built-in support for creating, propagating(`check` keyword), and handling errors. Error handling logic can be performed after testing if a given value is an error using the `is` keyword. category: System Management diff --git a/pages/learn/enterprise-integration-patterns/index.js b/pages/learn/enterprise-integration-patterns/index.js index 29a92ed7020..8db243f4a22 100644 --- a/pages/learn/enterprise-integration-patterns/index.js +++ b/pages/learn/enterprise-integration-patterns/index.js @@ -36,22 +36,19 @@ export async function getStaticProps() { const filePath = path.join(baseDirectory, file); const stats = fs.statSync(filePath); const bal = path.join(filePath, file + ".bal"); - if (stats.isDirectory() && fs.existsSync(bal)) { - if (!fs.existsSync(path.resolve(""))) { - - } - - const ymlPath = path.join(baseDirectory, file, file + ".yml"); - const name = file.replace(/-.|^./g, x => " " + x.slice(-1).toUpperCase()).trim(); - var pattern = loadYml(ymlPath); - pattern.name = pattern.name ?? name; - const category = pattern.category ?? "uncategorized"; - const existingCategory = patterns[category]; - if (existingCategory) { - existingCategory.push(pattern); - } else { - patterns[category] = [pattern]; - } + if (!stats.isDirectory() || !fs.existsSync(bal)) { + continue; + } + const ymlPath = path.join(baseDirectory, file, file + ".yml"); + const name = file.replace(/-.|^./g, x => " " + x.slice(-1).toUpperCase()).trim(); + var pattern = loadYml(ymlPath) || {}; + pattern.name = pattern.name ?? name; + const category = pattern.category ?? "uncategorized"; + const existingCategory = patterns[category]; + if (existingCategory) { + existingCategory.push(pattern); + } else { + patterns[category] = [pattern]; } } for (const category of Object.values(patterns)) { diff --git a/pages/learn/integration/integration-tutorials/[slug].js b/pages/learn/integration/integration-tutorials/[slug].js index 6a7bac8ce8b..2e2b364ae43 100644 --- a/pages/learn/integration/integration-tutorials/[slug].js +++ b/pages/learn/integration/integration-tutorials/[slug].js @@ -93,12 +93,21 @@ export default function PostPage({ frontmatter, content, slug, codes }) { property="og:description" content="A programming language for the cloud that makes it easier to use, combine, and create network services." /> + {/* */} - + + {/* */} - + + - - - -
    - - - - -

    Back to integration tutorials

    -
    - - -
    + + + +
    + + + + +

    Back to integration tutorials

    +
    + + +

    {frontmatter.title}

    @@ -157,7 +170,7 @@ export default function PostPage({ frontmatter, content, slug, codes }) {
    - +

    {frontmatter.intro}

    @@ -168,7 +181,7 @@ export default function PostPage({ frontmatter, content, slug, codes }) { + codes={codes} />
    diff --git a/pages/learn/integration/integration-tutorials/index.js b/pages/learn/integration/integration-tutorials/index.js index f83c0ccf62b..6d87694f4eb 100644 --- a/pages/learn/integration/integration-tutorials/index.js +++ b/pages/learn/integration/integration-tutorials/index.js @@ -63,7 +63,7 @@ export default function Learn() { {/* FB */} - + {/* LINKED IN */} - + diff --git a/pages/learn/integration/pre-built-integrations/ftp-edi-message-to-salesforce-opportunity.js b/pages/learn/integration/pre-built-integrations/ftp-edi-message-to-salesforce-opportunity.js index 6f6c5399608..fa7683ffd5d 100644 --- a/pages/learn/integration/pre-built-integrations/ftp-edi-message-to-salesforce-opportunity.js +++ b/pages/learn/integration/pre-built-integrations/ftp-edi-message-to-salesforce-opportunity.js @@ -327,9 +327,9 @@ export default function Learn({ samples, content }) {

    - + - Flow Diagram + Flow Diagram
    @@ -367,9 +367,9 @@ export default function Learn({ samples, content }) { - + - Sequence Diagram + Sequence Diagram diff --git a/pages/learn/integration/pre-built-integrations/github-to-email-integration.js b/pages/learn/integration/pre-built-integrations/github-to-email-integration.js index 4dfb0b609b1..f300a217e88 100644 --- a/pages/learn/integration/pre-built-integrations/github-to-email-integration.js +++ b/pages/learn/integration/pre-built-integrations/github-to-email-integration.js @@ -260,9 +260,9 @@ export default function Learn({ samples, content }) {

    - + - Flow Diagram + Flow Diagram
    @@ -301,8 +301,8 @@ export default function Learn({ samples, content }) { - - Sequence Diagram + + Sequence Diagram diff --git a/pages/learn/integration/pre-built-integrations/gmail-to-salesforce-integration.js b/pages/learn/integration/pre-built-integrations/gmail-to-salesforce-integration.js index fbf68885fbe..80a65159f54 100644 --- a/pages/learn/integration/pre-built-integrations/gmail-to-salesforce-integration.js +++ b/pages/learn/integration/pre-built-integrations/gmail-to-salesforce-integration.js @@ -375,9 +375,9 @@ export default function Learn({ samples, content }) {

    - + - Flow Diagram + Flow Diagram @@ -416,8 +416,8 @@ export default function Learn({ samples, content }) {
    - - Sequence Diagram + + Sequence Diagram diff --git a/pages/learn/integration/pre-built-integrations/google-drive-to-onedrive-integration.js b/pages/learn/integration/pre-built-integrations/google-drive-to-onedrive-integration.js index 75ce7085454..ff8bb24ec09 100644 --- a/pages/learn/integration/pre-built-integrations/google-drive-to-onedrive-integration.js +++ b/pages/learn/integration/pre-built-integrations/google-drive-to-onedrive-integration.js @@ -249,9 +249,9 @@ export default function Learn({ samples, content }) {

    - + - Flow Diagram + Flow Diagram @@ -290,8 +290,8 @@ export default function Learn({ samples, content }) {
    - - Sequence Diagram + + Sequence Diagram diff --git a/pages/learn/integration/pre-built-integrations/google-sheets-to-salesforce-integration.js b/pages/learn/integration/pre-built-integrations/google-sheets-to-salesforce-integration.js index 5dca79137f0..25ed67b86c0 100644 --- a/pages/learn/integration/pre-built-integrations/google-sheets-to-salesforce-integration.js +++ b/pages/learn/integration/pre-built-integrations/google-sheets-to-salesforce-integration.js @@ -247,9 +247,9 @@ export default function Learn({ samples, content }) {

    - + - Flow Diagram + Flow Diagram @@ -288,8 +288,8 @@ export default function Learn({ samples, content }) {
    - - Sequence Diagram + + Sequence Diagram diff --git a/pages/learn/integration/pre-built-integrations/hubspot-contacts-to-google-contacts-integration.js b/pages/learn/integration/pre-built-integrations/hubspot-contacts-to-google-contacts-integration.js index 61136ad29d3..722288ef182 100644 --- a/pages/learn/integration/pre-built-integrations/hubspot-contacts-to-google-contacts-integration.js +++ b/pages/learn/integration/pre-built-integrations/hubspot-contacts-to-google-contacts-integration.js @@ -239,9 +239,9 @@ export default function Learn({ samples, content }) {

    - + - Flow Diagram + Flow Diagram @@ -280,8 +280,8 @@ export default function Learn({ samples, content }) {
    - - Sequence Diagram + + Sequence Diagram diff --git a/pages/learn/integration/pre-built-integrations/kafka-to-salesforce-integration.js b/pages/learn/integration/pre-built-integrations/kafka-to-salesforce-integration.js index 678b9e67613..975f8fdc0d0 100644 --- a/pages/learn/integration/pre-built-integrations/kafka-to-salesforce-integration.js +++ b/pages/learn/integration/pre-built-integrations/kafka-to-salesforce-integration.js @@ -237,9 +237,9 @@ export default function Learn({ samples, content }) { based on the prices published to a Kafka topic.

    - + - Sequence Diagram + Sequence Diagram diff --git a/pages/learn/integration/pre-built-integrations/mysql-to-salesforce-integration.js b/pages/learn/integration/pre-built-integrations/mysql-to-salesforce-integration.js index 73d6bbecbe9..1f0b2b37f62 100644 --- a/pages/learn/integration/pre-built-integrations/mysql-to-salesforce-integration.js +++ b/pages/learn/integration/pre-built-integrations/mysql-to-salesforce-integration.js @@ -246,9 +246,9 @@ export default function Learn({ samples, content }) {

    - + - Flow Diagram + Flow Diagram @@ -287,8 +287,8 @@ export default function Learn({ samples, content }) {
    - - Sequence Diagram + + Sequence Diagram diff --git a/pages/learn/integration/pre-built-integrations/news-api-to-email-integration.js b/pages/learn/integration/pre-built-integrations/news-api-to-email-integration.js index 34037ad7b09..0859333c406 100644 --- a/pages/learn/integration/pre-built-integrations/news-api-to-email-integration.js +++ b/pages/learn/integration/pre-built-integrations/news-api-to-email-integration.js @@ -231,9 +231,9 @@ export default function Learn({ samples, content }) {

    - + - Flow Diagram + Flow Diagram @@ -272,8 +272,8 @@ export default function Learn({ samples, content }) {
    - - Sequence Diagram + + Sequence Diagram diff --git a/pages/learn/integration/pre-built-integrations/salesforce-to-twilio-integration.js b/pages/learn/integration/pre-built-integrations/salesforce-to-twilio-integration.js index 21137c2153a..8431f2cb049 100644 --- a/pages/learn/integration/pre-built-integrations/salesforce-to-twilio-integration.js +++ b/pages/learn/integration/pre-built-integrations/salesforce-to-twilio-integration.js @@ -259,9 +259,9 @@ export default function Learn({ samples, content }) {

    - + - Flow Diagram + Flow Diagram diff --git a/pages/learn/integration/pre-built-integrations/shopify-to-outlook-integration.js b/pages/learn/integration/pre-built-integrations/shopify-to-outlook-integration.js index 350269afb02..694b2e06e8b 100644 --- a/pages/learn/integration/pre-built-integrations/shopify-to-outlook-integration.js +++ b/pages/learn/integration/pre-built-integrations/shopify-to-outlook-integration.js @@ -259,9 +259,9 @@ export default function Learn({ samples, content }) { welcome emails to new customers.

    - + - Flow Diagram + Flow Diagram @@ -300,8 +300,8 @@ export default function Learn({ samples, content }) {
    - - Sequence Diagram + + Sequence Diagram diff --git a/pages/learn/references/ballerina-specifications.js b/pages/learn/references/ballerina-specifications.js index 8441fea02e6..8238a565ec5 100644 --- a/pages/learn/references/ballerina-specifications.js +++ b/pages/learn/references/ballerina-specifications.js @@ -76,11 +76,22 @@ export default function PostPage({ frontmatter, content, id }) { property="og:description" content={frontmatter.description} > + {/* */} + + {/* */} + + diff --git a/pages/spec/[slug].js b/pages/spec/[slug].js index 31e7f931861..91ceb0a692e 100644 --- a/pages/spec/[slug].js +++ b/pages/spec/[slug].js @@ -118,23 +118,28 @@ export default function PostPage({ frontmatter, content, codeSnippets }) { return newId; } + const extractLibraryNameFromContent = () => { + return content.split("\n")[0].substring(2); + } + return ( <> - {frontmatter.title} + {frontmatter.title || extractLibraryNameFromContent()} {/* */} - + {/* */} {/* */} + diff --git a/pages/usecases/b2b/index.js b/pages/usecases/b2b/index.js index b5d1602bcba..5cb2be36e8e 100644 --- a/pages/usecases/b2b/index.js +++ b/pages/usecases/b2b/index.js @@ -116,14 +116,14 @@ export default function Integrations({ samples }) { {/* LINKED IN */} diff --git a/pages/usecases/data-oriented-programming/index.js b/pages/usecases/data-oriented-programming/index.js index ece2ef40897..1913f18cb9e 100644 --- a/pages/usecases/data-oriented-programming/index.js +++ b/pages/usecases/data-oriented-programming/index.js @@ -129,14 +129,14 @@ export default function Integrations({ samples }) { {/* LINKED IN */} - + - + diff --git a/pages/usecases/microservices/index.js b/pages/usecases/microservices/index.js index f249df38e3a..6a938206076 100644 --- a/pages/usecases/microservices/index.js +++ b/pages/usecases/microservices/index.js @@ -116,14 +116,14 @@ export default function Integrations({ samples }) { {/* LINKED IN */} diff --git a/public/hacktoberfest/ballerina-hacktoberfest-2023-terms-and-onditions.pdf b/public/hacktoberfest/ballerina-hacktoberfest-2023-terms-and-onditions.pdf new file mode 100644 index 00000000000..2bf2a9cc215 Binary files /dev/null and b/public/hacktoberfest/ballerina-hacktoberfest-2023-terms-and-onditions.pdf differ diff --git a/public/images/GLOBAL_Ballerina_Hacktoberfest 2023_Banner_Oct23.png b/public/images/GLOBAL_Ballerina_Hacktoberfest 2023_Banner_Oct23.png new file mode 100644 index 00000000000..cd0ea8a7ffd Binary files /dev/null and b/public/images/GLOBAL_Ballerina_Hacktoberfest 2023_Banner_Oct23.png differ diff --git a/public/images/ballerina-learn-ballerina-by-example-page-sm-banner.png b/public/images/ballerina-learn-ballerina-by-example-page-sm-banner.png new file mode 100644 index 00000000000..672ddcaa5a2 Binary files /dev/null and b/public/images/ballerina-learn-ballerina-by-example-page-sm-banner.png differ diff --git a/public/images/ballerina-learn-ballerina-specifications-page-sm-banner.png b/public/images/ballerina-learn-ballerina-specifications-page-sm-banner.png new file mode 100644 index 00000000000..729b23d4e13 Binary files /dev/null and b/public/images/ballerina-learn-ballerina-specifications-page-sm-banner.png differ diff --git a/public/images/ballerina-learn-integration-tutorials-page-sm-banner.png b/public/images/ballerina-learn-integration-tutorials-page-sm-banner.png new file mode 100644 index 00000000000..724c3c129f8 Binary files /dev/null and b/public/images/ballerina-learn-integration-tutorials-page-sm-banner.png differ diff --git a/public/images/ballerina-use-cases-b2b-integration-sm-banner.png b/public/images/ballerina-use-cases-b2b-integration-sm-banner.png new file mode 100644 index 00000000000..d1118ac8e0e Binary files /dev/null and b/public/images/ballerina-use-cases-b2b-integration-sm-banner.png differ diff --git a/public/images/ballerina-use-cases-microservices-sm-banner.png b/public/images/ballerina-use-cases-microservices-sm-banner.png new file mode 100644 index 00000000000..dd7fddb77ef Binary files /dev/null and b/public/images/ballerina-use-cases-microservices-sm-banner.png differ diff --git a/public/images/case-studies/mosip-sm-banner.png b/public/images/case-studies/mosip-sm-banner.png new file mode 100644 index 00000000000..5075f5582e4 Binary files /dev/null and b/public/images/case-studies/mosip-sm-banner.png differ diff --git a/public/images/case-studies/wso2-sm-banner.png b/public/images/case-studies/wso2-sm-banner.png new file mode 100644 index 00000000000..b5d419f5dbe Binary files /dev/null and b/public/images/case-studies/wso2-sm-banner.png differ diff --git a/public/images/home-page/user-logos/fat-tuesday.svg b/public/images/home-page/user-logos/fat-tuesday.svg new file mode 100644 index 00000000000..33a502c0f70 --- /dev/null +++ b/public/images/home-page/user-logos/fat-tuesday.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/public/images/home-page/user-logos/qhana.png b/public/images/home-page/user-logos/qhana.png new file mode 100644 index 00000000000..f66b7077b0c Binary files /dev/null and b/public/images/home-page/user-logos/qhana.png differ diff --git a/public/images/patterns/canonical-data-model.svg b/public/images/patterns/canonical-data-model.svg new file mode 100644 index 00000000000..c3eec7b28f4 --- /dev/null +++ b/public/images/patterns/canonical-data-model.svg @@ -0,0 +1,89 @@ + + diff --git a/public/images/patterns/channel-adapter.svg b/public/images/patterns/channel-adapter.svg new file mode 100644 index 00000000000..9aa2e934854 --- /dev/null +++ b/public/images/patterns/channel-adapter.svg @@ -0,0 +1,25 @@ + + diff --git a/public/images/patterns/command-message.svg b/public/images/patterns/command-message.svg new file mode 100644 index 00000000000..02a4fc40679 --- /dev/null +++ b/public/images/patterns/command-message.svg @@ -0,0 +1,2 @@ + +C diff --git a/public/images/patterns/composed-message-processor.svg b/public/images/patterns/composed-message-processor.svg new file mode 100644 index 00000000000..8c5e4f41846 --- /dev/null +++ b/public/images/patterns/composed-message-processor.svg @@ -0,0 +1,2 @@ + + diff --git a/public/images/patterns/correlation-identifier.svg b/public/images/patterns/correlation-identifier.svg new file mode 100644 index 00000000000..61e12b5b309 --- /dev/null +++ b/public/images/patterns/correlation-identifier.svg @@ -0,0 +1,115 @@ + +AB diff --git a/public/images/patterns/envelope-wrapper.svg b/public/images/patterns/envelope-wrapper.svg new file mode 100644 index 00000000000..00032634382 --- /dev/null +++ b/public/images/patterns/envelope-wrapper.svg @@ -0,0 +1,10 @@ + + diff --git a/public/images/patterns/idempotent-receiver.svg b/public/images/patterns/idempotent-receiver.svg new file mode 100644 index 00000000000..a765810feda --- /dev/null +++ b/public/images/patterns/idempotent-receiver.svg @@ -0,0 +1,85 @@ + +1 diff --git a/public/images/patterns/message-channel.svg b/public/images/patterns/message-channel.svg new file mode 100644 index 00000000000..9db4535bb02 --- /dev/null +++ b/public/images/patterns/message-channel.svg @@ -0,0 +1,2 @@ + + diff --git a/public/images/patterns/message-endpoint.svg b/public/images/patterns/message-endpoint.svg new file mode 100644 index 00000000000..9a10b772d77 --- /dev/null +++ b/public/images/patterns/message-endpoint.svg @@ -0,0 +1,2 @@ + + diff --git a/public/images/patterns/message.svg b/public/images/patterns/message.svg new file mode 100644 index 00000000000..7ffa0c01ba6 --- /dev/null +++ b/public/images/patterns/message.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/patterns/messaging-gateway.svg b/public/images/patterns/messaging-gateway.svg new file mode 100644 index 00000000000..c77ed259d4e --- /dev/null +++ b/public/images/patterns/messaging-gateway.svg @@ -0,0 +1,99 @@ + + diff --git a/public/images/patterns/pipes-and-filters.svg b/public/images/patterns/pipes-and-filters.svg new file mode 100644 index 00000000000..dad6bf4a3e6 --- /dev/null +++ b/public/images/patterns/pipes-and-filters.svg @@ -0,0 +1,110 @@ + + diff --git a/public/images/patterns/point-to-point-channel.svg b/public/images/patterns/point-to-point-channel.svg new file mode 100644 index 00000000000..49d30d215df --- /dev/null +++ b/public/images/patterns/point-to-point-channel.svg @@ -0,0 +1,81 @@ + + diff --git a/public/images/patterns/polling-consumer-opt.svg b/public/images/patterns/polling-consumer-opt.svg deleted file mode 100644 index 50a728cc9c2..00000000000 --- a/public/images/patterns/polling-consumer-opt.svg +++ /dev/null @@ -1,30 +0,0 @@ - - diff --git a/public/images/patterns/recipient-list.svg b/public/images/patterns/recipient-list.svg new file mode 100644 index 00000000000..09a2141ec16 --- /dev/null +++ b/public/images/patterns/recipient-list.svg @@ -0,0 +1,103 @@ + + diff --git a/public/images/patterns/resequencer.svg b/public/images/patterns/resequencer.svg new file mode 100644 index 00000000000..2e4c0750dc1 --- /dev/null +++ b/public/images/patterns/resequencer.svg @@ -0,0 +1,104 @@ + + diff --git a/public/images/patterns/selective-consumer.svg b/public/images/patterns/selective-consumer.svg new file mode 100644 index 00000000000..25e9871e9ca --- /dev/null +++ b/public/images/patterns/selective-consumer.svg @@ -0,0 +1,113 @@ + +? diff --git a/public/images/patterns/service-activator.svg b/public/images/patterns/service-activator.svg new file mode 100644 index 00000000000..4620f85f749 --- /dev/null +++ b/public/images/patterns/service-activator.svg @@ -0,0 +1,103 @@ + + diff --git a/public/images/sm-icons/twitter-2023.svg b/public/images/sm-icons/twitter-2023.svg new file mode 100644 index 00000000000..437e2bfddbb --- /dev/null +++ b/public/images/sm-icons/twitter-2023.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/usecases/integration/ballerina-use-cases-data-oriented-programming-sm-banner.png b/public/images/usecases/integration/ballerina-use-cases-data-oriented-programming-sm-banner.png new file mode 100644 index 00000000000..96160014c46 Binary files /dev/null and b/public/images/usecases/integration/ballerina-use-cases-data-oriented-programming-sm-banner.png differ diff --git a/public/spec/graphql/spec.md b/public/spec/graphql/spec.md index 0837c8930f9..0b97d52b759 100644 --- a/public/spec/graphql/spec.md +++ b/public/spec/graphql/spec.md @@ -896,6 +896,8 @@ enum Direction { } ``` +>**Note:** While it is possible to assign a `string` value to an `enum` member in the Ballerina language, the GraphQL specification does not support this behaviour. Therefore, it's not recommended to use `string` values for `enum` members when defining an `enum` type for use in a `graphql:Service`. Using `string` values for `enum` members may result in an invalid generated schema. + ### 4.5 Input Types In GraphQL, a field can have zero or more input arguments. These arguments can be either a [`Scalar` type](#41-scalars), an [`Enum` type](#44-enums), or an [`INPUT_OBJECT` type](#452-input-objects). @@ -958,7 +960,7 @@ type Book record {| The input arguments of a GraphQL field can have default values. In Ballerina, this is allowed by providing default values to input parameters of a `resource` or `remote` method that represents a GraphQL field. When a `resource` or `remote` method input parameter has a default value, it will be added to the generated GraphQL schema. Then, the input parameter can be omitted in the GraphQL document, even if the input type is `NON_NULL`. ->**Note:** Currently, the generated schema does not include the default value of an input parameter due to a Ballerina language limitation. It shows an empty string instead of the default value. This only affects when accessing the generated schema via introspection or file generation. It does not affect the functionality of the default values. +>**Note:** To generate a schema with a valid default value, remember to use either a literal value, a list constructor expression, or a mapping constructor expression for the default parameters or input object fields. The generated schema will use an empty string if the default value is not one of the mentioned types of expressions. Avoid using other types of expressions, such as variable assignment, as they may result in an invalid schema. ###### Example: Default Values diff --git a/public/spec/soap/spec.md b/public/spec/soap/spec.md new file mode 100644 index 00000000000..e7469af6fc0 --- /dev/null +++ b/public/spec/soap/spec.md @@ -0,0 +1,104 @@ +# Specification: Ballerina Soap Library + +_Owners_: @shafreenAnfar @MadhukaHarith92 +_Reviewers_: @shafreenAnfar +_Created_: 2023/06/07 +_Updated_: 2023/08/14 +_Edition_: Swan Lake + +## Introduction +This is the specification for the Soap standard library of [Ballerina language](https://ballerina.io/), which provides APIs to send an ordinary XML request to a SOAP backend by specifying the necessary details to construct a SOAP envelope. + +The Soap library specification has evolved and may continue to evolve in the future. The released versions of the specification can be found under the relevant GitHub tag. + +If you have any feedback or suggestions about the library, start a discussion via a [GitHub issue](https://github.com/ballerina-platform/ballerina-standard-library/issues) or in the [Discord server](https://discord.gg/ballerinalang). Based on the outcome of the discussion, the specification and implementation can be updated. Community feedback is always welcome. Any accepted proposal, which affects the specification is stored under `/docs/proposals`. Proposals under discussion can be found with the label `type/proposal` in GitHub. + +The conforming implementation of the specification is released and included in the distribution. Any deviation from the specification is considered a bug. + +## Contents + +1. [Overview](#1-overview) +2. [Components](#2-components) + * 2.1 [Client](#21-client) + * 2.1.1 [Initializing the Client](#211-initializing-the-client) + * 2.1.2 [SendReceive](#211-sendreceive) + * 2.1.3 [SendOnly](#213-sendonly) +3. [Supported SOAP Versions](#3-supported-soap-versions) + +## 1. Overview +This specification elaborates on the functions available in the Soap library. + +The soap module abstracts out the details of the creation of a SOAP envelope, headers, and the body in a SOAP message. + +## 2. Components +This section describes the components of the Ballerina SOAP package. To use the Ballerina SOAP package, a user must import the Ballerina SOAP package first. +```ballerina +import ballerina/soap; +``` + +### 2.1 Client + +The SOAP client can be used to connect to a SOAP service and retrieve data. + +#### 2.1.1 Initializing the Client + +The `soap:Client` `init` method requires a valid URL and optional configuration to initialize the client. + +#### 2.1.2 SendReceive + +The `sendReceive` function sends SOAP request and expects a response. + +```ballerina +import ballerina/io; +import ballerina/soap; +import ballerina/mime; + +public function main () returns error? { + + soap:Client soapClient = check new("http://ws.cdyne.com/phoneverify/phoneverify.asmx?wsdl"); + + xml body = xml ` + 18006785432 + 0 + `; + + xml|mime:Entity[] response = check soapClient->sendReceive(body); + io:println(response); +} +``` + +#### 2.1.3 SendOnly + +The `sendOnly` function fires and forgets requests. It sends the request without the possibility of any response from the service (even an error). + +```ballerina +import ballerina/io; +import ballerina/soap; +import ballerina/mime; + +public function main () returns error? { + + soap:Client soapClient = check new("http://ws.cdyne.com/phoneverify/phoneverify.asmx?wsdl"); + + xml body = xml ` + 18006785432 + 0 + `; + + check soapClient->sendOnly(body); +} +``` + +## 3. Supported SOAP Versions + +The soap module supports SOAP 1.1 and 1.2 versions. By default, the soap client is configured to work with SOAP 1.1. Users can overwrite this to support SOAP 1.2 by passing `soapVersion` +parameter during client initialization. + +```ballerina +import ballerina/soap; + +public function main () returns error? { + + soap:Client soapClient = check new("http://ws.cdyne.com/phoneverify/phoneverify.asmx?wsdl", soapVersion = SOAP12); +} +``` diff --git a/spec/graphql/spec.md b/spec/graphql/spec.md index 0837c8930f9..0b97d52b759 100644 --- a/spec/graphql/spec.md +++ b/spec/graphql/spec.md @@ -896,6 +896,8 @@ enum Direction { } ``` +>**Note:** While it is possible to assign a `string` value to an `enum` member in the Ballerina language, the GraphQL specification does not support this behaviour. Therefore, it's not recommended to use `string` values for `enum` members when defining an `enum` type for use in a `graphql:Service`. Using `string` values for `enum` members may result in an invalid generated schema. + ### 4.5 Input Types In GraphQL, a field can have zero or more input arguments. These arguments can be either a [`Scalar` type](#41-scalars), an [`Enum` type](#44-enums), or an [`INPUT_OBJECT` type](#452-input-objects). @@ -958,7 +960,7 @@ type Book record {| The input arguments of a GraphQL field can have default values. In Ballerina, this is allowed by providing default values to input parameters of a `resource` or `remote` method that represents a GraphQL field. When a `resource` or `remote` method input parameter has a default value, it will be added to the generated GraphQL schema. Then, the input parameter can be omitted in the GraphQL document, even if the input type is `NON_NULL`. ->**Note:** Currently, the generated schema does not include the default value of an input parameter due to a Ballerina language limitation. It shows an empty string instead of the default value. This only affects when accessing the generated schema via introspection or file generation. It does not affect the functionality of the default values. +>**Note:** To generate a schema with a valid default value, remember to use either a literal value, a list constructor expression, or a mapping constructor expression for the default parameters or input object fields. The generated schema will use an empty string if the default value is not one of the mentioned types of expressions. Avoid using other types of expressions, such as variable assignment, as they may result in an invalid schema. ###### Example: Default Values diff --git a/spec/soap/spec.md b/spec/soap/spec.md new file mode 100644 index 00000000000..e7469af6fc0 --- /dev/null +++ b/spec/soap/spec.md @@ -0,0 +1,104 @@ +# Specification: Ballerina Soap Library + +_Owners_: @shafreenAnfar @MadhukaHarith92 +_Reviewers_: @shafreenAnfar +_Created_: 2023/06/07 +_Updated_: 2023/08/14 +_Edition_: Swan Lake + +## Introduction +This is the specification for the Soap standard library of [Ballerina language](https://ballerina.io/), which provides APIs to send an ordinary XML request to a SOAP backend by specifying the necessary details to construct a SOAP envelope. + +The Soap library specification has evolved and may continue to evolve in the future. The released versions of the specification can be found under the relevant GitHub tag. + +If you have any feedback or suggestions about the library, start a discussion via a [GitHub issue](https://github.com/ballerina-platform/ballerina-standard-library/issues) or in the [Discord server](https://discord.gg/ballerinalang). Based on the outcome of the discussion, the specification and implementation can be updated. Community feedback is always welcome. Any accepted proposal, which affects the specification is stored under `/docs/proposals`. Proposals under discussion can be found with the label `type/proposal` in GitHub. + +The conforming implementation of the specification is released and included in the distribution. Any deviation from the specification is considered a bug. + +## Contents + +1. [Overview](#1-overview) +2. [Components](#2-components) + * 2.1 [Client](#21-client) + * 2.1.1 [Initializing the Client](#211-initializing-the-client) + * 2.1.2 [SendReceive](#211-sendreceive) + * 2.1.3 [SendOnly](#213-sendonly) +3. [Supported SOAP Versions](#3-supported-soap-versions) + +## 1. Overview +This specification elaborates on the functions available in the Soap library. + +The soap module abstracts out the details of the creation of a SOAP envelope, headers, and the body in a SOAP message. + +## 2. Components +This section describes the components of the Ballerina SOAP package. To use the Ballerina SOAP package, a user must import the Ballerina SOAP package first. +```ballerina +import ballerina/soap; +``` + +### 2.1 Client + +The SOAP client can be used to connect to a SOAP service and retrieve data. + +#### 2.1.1 Initializing the Client + +The `soap:Client` `init` method requires a valid URL and optional configuration to initialize the client. + +#### 2.1.2 SendReceive + +The `sendReceive` function sends SOAP request and expects a response. + +```ballerina +import ballerina/io; +import ballerina/soap; +import ballerina/mime; + +public function main () returns error? { + + soap:Client soapClient = check new("http://ws.cdyne.com/phoneverify/phoneverify.asmx?wsdl"); + + xml body = xml ` + 18006785432 + 0 + `; + + xml|mime:Entity[] response = check soapClient->sendReceive(body); + io:println(response); +} +``` + +#### 2.1.3 SendOnly + +The `sendOnly` function fires and forgets requests. It sends the request without the possibility of any response from the service (even an error). + +```ballerina +import ballerina/io; +import ballerina/soap; +import ballerina/mime; + +public function main () returns error? { + + soap:Client soapClient = check new("http://ws.cdyne.com/phoneverify/phoneverify.asmx?wsdl"); + + xml body = xml ` + 18006785432 + 0 + `; + + check soapClient->sendOnly(body); +} +``` + +## 3. Supported SOAP Versions + +The soap module supports SOAP 1.1 and 1.2 versions. By default, the soap client is configured to work with SOAP 1.1. Users can overwrite this to support SOAP 1.2 by passing `soapVersion` +parameter during client initialization. + +```ballerina +import ballerina/soap; + +public function main () returns error? { + + soap:Client soapClient = check new("http://ws.cdyne.com/phoneverify/phoneverify.asmx?wsdl", soapVersion = SOAP12); +} +``` diff --git a/utils/archived-lm.json b/utils/archived-lm.json index 1cb532c51bd..047db806372 100644 --- a/utils/archived-lm.json +++ b/utils/archived-lm.json @@ -22,6 +22,14 @@ "url": "https://lib.ballerina.io/", "id": "swan-lake-api-docs" }, + { + "dirName": "2201.8.1", + "level": 2, + "position": 1, + "isDir": false, + "url": "#2201.8.1", + "id": "2201.8.1v" + }, { "dirName": "2201.8.0", "level": 2, @@ -457,6 +465,14 @@ "url": "/1.2/learn/api-docs/ballerina/", "id": "1.2.x-api-docs" }, + { + "dirName": "1.2.45", + "level": 2, + "position": 1, + "isDir": false, + "url": "#1.2.45", + "id": "1.2.45v" + }, { "dirName": "1.2.44", "level": 2, diff --git a/utils/rl.json b/utils/rl.json index b0f6c6dfac7..ef2d4403f74 100644 --- a/utils/rl.json +++ b/utils/rl.json @@ -14,6 +14,14 @@ "url": "/downloads/swan-lake-release-notes", "id": "swan-lake-release-notes", "subDirectories": [ + { + "dirName": "2201.8.2 (Swan Lake Update 8)", + "level": 2, + "position": 1, + "isDir": false, + "url": "/downloads/swan-lake-release-notes/swan-lake-2201.8.2", + "id": "swan-lake-2201.8.2" + }, { "dirName": "2201.8.1 (Swan Lake Update 8)", "level": 2, @@ -459,6 +467,14 @@ "url": "/downloads/1.2.x-release-notes", "id": "1.2.x-release-notes", "subDirectories": [ + { + "dirName": "1.2.45", + "level": 2, + "position": 1, + "isDir": false, + "url": "/downloads/1.2.x-release-notes/1.2.45", + "id": "1.2.45" + }, { "dirName": "1.2.44", "level": 2,