From 9063336687c06fe1100742d8b2c149cc2dbb13cd Mon Sep 17 00:00:00 2001 From: Shrirang Date: Sat, 11 Dec 2021 20:29:36 +0530 Subject: [PATCH] feature: Claim check pattern azure (#1897) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Archietecture Diagram added * Added pom.xml * Architecture Diagram Updated * Added Microservices and kafka * ReadME File Added * ReadME file Updated * #1329 ReadMe file updated and working pattern code added * #1329 readme file updated * #1329 readme file updated and java documentation added * #1329 repository merged * Update claim-check-pattern/ReadME.md #1329 Real world description updated Co-authored-by: Subhrodip Mohanta * #1329 Update claim-check-pattern/ReadME.md Co-authored-by: Subhrodip Mohanta * #1329 Applicability section in ReadMe file updated Co-authored-by: Subhrodip Mohanta * #1329 Tutorial section in ReadMe file updated Co-authored-by: Subhrodip Mohanta * #1329 Storage Data section in ReadMe File updated Co-authored-by: Subhrodip Mohanta * #1329 workflow section Update claim-check-pattern/ReadME.md Co-authored-by: Subhrodip Mohanta * #1329 Update claim-check-pattern/pom.xml Co-authored-by: Subhrodip Mohanta * #1329 deleted mvnw.cmd file * #1329 deleted drawio file * #1329 deleted mvnw file * #1329 deleted mvnw file * #1329 mvnw.cmd file deleted * #1329 Update claim-check-pattern/usage-cost-processor/src/main/java/com/callusage/domain/MessageHeader.java Co-authored-by: Subhrodip Mohanta * #1329 Update claim-check-pattern/usage-cost-processor/src/main/java/com/callusage/domain/UsageCostDetail.java Co-authored-by: Subhrodip Mohanta * #1329 Update claim-check-pattern/usage-cost-processor/src/main/java/com/callusage/domain/UsageDetail.java Co-authored-by: Subhrodip Mohanta * #1329 deleted mvnw file * #1329 deleted mvnw.cmd file * #1329 Update claim-check-pattern/usage-detail-sender/src/main/java/com/callusage/domain/Message.java Co-authored-by: Subhrodip Mohanta * #1329 Update claim-check-pattern/ReadME.md Co-authored-by: Subhrodip Mohanta * #1329 pom file dependencies fixed, readmeflie updated, removed unused imports * #1329 Readfile updated, class javadoc added * #1329 UML class diagrams added, readme file updated * #1329 lombok annotations used on model classes, common dependencies moved to parent pom * #1329 test cases added * include claim-check-pattern in parent pom * #1329 code smells fixed * #1329 code smells removed * #1329 security issues fixed * #1329 updated pom files and refactored packages name * #1329 checkstyle warning fixed * #1329 code coverage increased * #1329 minor changed. * checkpoint created with common utility * Claim-Check-Pattern | Shrirang97 | Implemented using Java Azure Functions * Claim-Check-Pattern | Shrirang97 | Updated Functions logic * Update MessageHandlerUtility.java * Update UsageCostProcessorFunction.java * claim-check-pattern | Shrirang97 | Added test cases * claim-check-pattern | Shrirang97 | Test cases for Azure functions fixed * Claim-Check-Pattern | Shrirang | Used string as request body * claim-check-pattern | Shrirang | Working test cases * claim-check-pattern | Shrirang | Issue fixed while deserializing * claim-check-pattern | Shrirang | removed unused import * claim-check-pattern | Shrirang | fixed refactoring * claim-chek-pattern | Shrirang | added lombok | fixed dependencies & test cases * Delete .DS_Store * claim-check-pattern | Shrirang | Fixed unrelated file * Update BookService.java * Update BookService.java * claim-check-pattern | Shrirang | Fixed unrelated files * claim-check-pattern | Shrirang | Fixed review comments * Update UsageCostProcessorFunction.java * Update ReadME.md * Rename ReadME.md to README.md * claim-check-pattern | Shrirang | Incorporated review comments. * Update cloud-claim-check-pattern/README.md Co-authored-by: Ilkka Seppälä * Update cloud-claim-check-pattern/README.md Co-authored-by: Ilkka Seppälä * Update cloud-claim-check-pattern/README.md Co-authored-by: Ilkka Seppälä * Update cloud-claim-check-pattern/README.md Co-authored-by: Ilkka Seppälä * Update cloud-claim-check-pattern/README.md Co-authored-by: Ilkka Seppälä * Update cloud-claim-check-pattern/README.md Co-authored-by: Ilkka Seppälä * Update cloud-claim-check-pattern/README.md Co-authored-by: Ilkka Seppälä * Updated readme file * Read me file updated | Added more description Co-authored-by: Subhrodip Mohanta Co-authored-by: Subhrodip Mohanta Co-authored-by: Ilkka Seppälä --- cloud-claim-check-pattern/.gitignore | 38 ++++ cloud-claim-check-pattern/README.md | 82 ++++++++ .../call-usage-app/.gitignore | 38 ++++ .../etc/call-usage-app.urm.puml | 117 +++++++++++ .../call-usage-app/host.json | 7 + .../call-usage-app/pom.xml | 150 +++++++++++++++ .../functions/UsageCostProcessorFunction.java | 168 ++++++++++++++++ .../claimcheckpattern/domain/Message.java | 43 +++++ .../claimcheckpattern/domain/MessageBody.java | 43 +++++ .../domain/MessageHeader.java | 47 +++++ .../domain/MessageReference.java | 45 +++++ .../domain/UsageCostDetail.java | 43 +++++ .../claimcheckpattern/domain/UsageDetail.java | 44 +++++ .../UsageDetailPublisherFunction.java | 146 ++++++++++++++ .../utility/EventHandlerUtility.java | 66 +++++++ .../utility/MessageHandlerUtility.java | 127 ++++++++++++ .../HttpResponseMessageMock.java | 105 ++++++++++ .../UsageCostProcessorFunctionTest.java | 181 ++++++++++++++++++ .../UsageDetailPublisherFunctionTest.java | 119 ++++++++++++ .../utility/EventHandlerUtilityTest.java | 70 +++++++ .../utility/MessageHandlerUtilityTest.java | 114 +++++++++++ .../org.mockito.plugins.MockMaker | 1 + .../subscriptionValidationEvent.json | 15 ++ .../src/test/resources/usageDetailEvent.json | 15 ++ .../etc/Claim-Check-Pattern.png | Bin 0 -> 53447 bytes .../etc/claim-check-pattern.urm.puml | 117 +++++++++++ .../etc/class-diagram.png | Bin 0 -> 110789 bytes cloud-claim-check-pattern/pom.xml | 69 +++++++ 28 files changed, 2010 insertions(+) create mode 100644 cloud-claim-check-pattern/.gitignore create mode 100644 cloud-claim-check-pattern/README.md create mode 100644 cloud-claim-check-pattern/call-usage-app/.gitignore create mode 100644 cloud-claim-check-pattern/call-usage-app/etc/call-usage-app.urm.puml create mode 100644 cloud-claim-check-pattern/call-usage-app/host.json create mode 100644 cloud-claim-check-pattern/call-usage-app/pom.xml create mode 100644 cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/consumer/callcostprocessor/functions/UsageCostProcessorFunction.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/Message.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/MessageBody.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/MessageHeader.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/MessageReference.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/UsageCostDetail.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/UsageDetail.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/producer/calldetails/functions/UsageDetailPublisherFunction.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/utility/EventHandlerUtility.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/utility/MessageHandlerUtility.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/HttpResponseMessageMock.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/consumer/callcostprocessor/functions/UsageCostProcessorFunctionTest.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/producer/calldetails/functions/UsageDetailPublisherFunctionTest.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/utility/EventHandlerUtilityTest.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/utility/MessageHandlerUtilityTest.java create mode 100644 cloud-claim-check-pattern/call-usage-app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker create mode 100644 cloud-claim-check-pattern/call-usage-app/src/test/resources/subscriptionValidationEvent.json create mode 100644 cloud-claim-check-pattern/call-usage-app/src/test/resources/usageDetailEvent.json create mode 100644 cloud-claim-check-pattern/etc/Claim-Check-Pattern.png create mode 100644 cloud-claim-check-pattern/etc/claim-check-pattern.urm.puml create mode 100644 cloud-claim-check-pattern/etc/class-diagram.png create mode 100644 cloud-claim-check-pattern/pom.xml diff --git a/cloud-claim-check-pattern/.gitignore b/cloud-claim-check-pattern/.gitignore new file mode 100644 index 000000000..f508cf94f --- /dev/null +++ b/cloud-claim-check-pattern/.gitignore @@ -0,0 +1,38 @@ +# Build output +target/ +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# IDE +.idea/ +*.iml +.settings/ +.project +.classpath + +# macOS +.DS_Store + +# Azure Functions +local.settings.json +bin/ +obj/ diff --git a/cloud-claim-check-pattern/README.md b/cloud-claim-check-pattern/README.md new file mode 100644 index 000000000..0259f5782 --- /dev/null +++ b/cloud-claim-check-pattern/README.md @@ -0,0 +1,82 @@ +--- +layout: pattern +title: Claim Check Pattern +folder: cloud-claim-check-pattern +permalink: /patterns/cloud-claim-check-pattern/ +categories: Cloud +tags: + - Cloud distributed + - Microservices +--- + +## Name + +[Claim Check Pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/claim-check) + +## Also known as + +[Reference-Based Messaging](https://www.enterpriseintegrationpatterns.com/patterns/messaging/StoreInLibrary.html) + +## Intent + +- Reduce the load of data transfer through the Internet. Instead of sending actual data directly, just send the message reference. +- Improve data security. As only message reference is shared, no data is exposed to the Internet. + +## Explanation + +Real-World Example + +> Suppose if you want to build a photo processing system. A photo processing system takes an image as input, processes it, and outputs a different set of images. Consider system has one persistent storage, one input component, ten processing components, messaging platform. Once a photo is given to the input component, it stores that image on persistent storage. It then creates ten different messages/events with the same image location and publishes them to the messaging platform. The messaging platform triggers ten different processing components. The ten processing components extract information about image location from the received event and then read an image from persistent storage. They generate ten different images from the original image and drop these images again to persistent storage. + +In Plain words + +> Split a large message into a claim check and a payload. Send the claim check to the messaging platform and store the payload to an external service. This pattern allows large messages to be processed while protecting the message bus and the client from being overwhelmed or slowed down. This pattern also helps to reduce costs, as storage is usually cheaper than resource units used by the messaging platform.([ref](https://docs.microsoft.com/en-us/azure/architecture/patterns/claim-check)) + +## Architecture Diagram + +![alt text](./etc/Claim-Check-Pattern.png "Claim Check Pattern") + +## Applicability + +Use the Claim Check Pattern when + +- Huge processing data causes a lot of bandwidth consumption to transfer data through the Internet. +- To secure your data transfer by storing in common persistent storage. +- Using a cloud platform - Azure Functions or AWS Lambda, Azure EventGrid or AWS Event Bridge, Azure Blob Storage or AWS S3 Bucket. +- Each service must be independent and idempotent. Output data is dropped to persistent storage by the service. +- Publish-subscribe messaging pattern needs to be used. + +## Consequences + +- This pattern is stateless. Any compute API will not store any data. +- You must have persistent storage and a reliable messaging platform. + +## Tutorials + +### Workflow + +Suppose a telecom company wants to build call cost calculator system which generate the call cost daily. At the end of each day, details of the calls made by the consumers are stored somewhere. The call calculator system will read this data and generate call cost data for each user. Consumers will be billed using this generated data in case of postpaid service. + +Producer class( `UsageDetailPublisherFunction` Azure Function) will generate call usage details (here we are generating call data in producer class itself. In real world scenario, it will read from storage). `UsageDetailPublisherFunction` creates a message. Message consists of message header and message body. Message header is basically an event grid event or claim or message reference. Message body contains actual data. `UsageDetailPublisherFunction` sends a message header to Event Grid topic `usage-detail` and drops an entire message to the blob storage. Event Grid then sent this message header to the `UsageCostProcessorFunction` Azure function. It will read the entire message from blob storage with the help of the header, will calculate call cost and drop the result to the blob storage. + +### Class Diagrams + +![alt text](./etc/class-diagram.png "Claim-Check-Class-Diagram") + +### Setup + +- Any operating system can be used macOS, Windows, Linux as everything is deployed on Azure. +- Install Java JDK 11 and set up Java environmental variables. +- Install Git. +- Install Visual Studio Code. +- Install [ Azure Functions extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions) to be able to deploy using Visual studio. + +### Storage Data + +The data is stored in the Azure blob storage in the container `callusageapp`. For every trigger, one GUID is created. Under the `GUID folder`, 2 files will be created `input.json` and `output.json`. +`Input.json` is dropped `producer` azure function which contains call usage details.` Output.json` contains call cost details which are dropped by the `consumer` azure function. + +## Credits + +- [Messaging Pattern - Claim Check](https://www.enterpriseintegrationpatterns.com/patterns/messaging/StoreInLibrary.html) +- [Azure Architecture Pattern - Claim Check Pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/claim-check) diff --git a/cloud-claim-check-pattern/call-usage-app/.gitignore b/cloud-claim-check-pattern/call-usage-app/.gitignore new file mode 100644 index 000000000..f508cf94f --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/.gitignore @@ -0,0 +1,38 @@ +# Build output +target/ +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# IDE +.idea/ +*.iml +.settings/ +.project +.classpath + +# macOS +.DS_Store + +# Azure Functions +local.settings.json +bin/ +obj/ diff --git a/cloud-claim-check-pattern/call-usage-app/etc/call-usage-app.urm.puml b/cloud-claim-check-pattern/call-usage-app/etc/call-usage-app.urm.puml new file mode 100644 index 000000000..0ffec48b1 --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/etc/call-usage-app.urm.puml @@ -0,0 +1,117 @@ +@startuml +package com.iluwatar.claimcheckpattern.producer.calldetails.functions { + class UsageDetailPublisherFunction { + - eventHandlerUtility : EventHandlerUtility + - messageHandlerUtility : MessageHandlerUtility + + UsageDetailPublisherFunction() + + UsageDetailPublisherFunction(messageHandlerUtility : MessageHandlerUtility, eventHandlerUtility : EventHandlerUtility) + + run(request : HttpRequestMessage>, context : ExecutionContext) : HttpResponseMessage + } +} +package com.iluwatar.claimcheckpattern.domain { + class Message { + - messageBody : MessageBody + - messageHeader : MessageHeader + + Message() + + getMessageBody() : MessageBody + + getMessageHeader() : MessageHeader + + setMessageBody(messageBody : MessageBody) + + setMessageHeader(messageHeader : MessageHeader) + } + class MessageBody { + - data : List + + MessageBody() + + getData() : List + + setData(data : List) + } + class MessageHeader { + - data : Object + - dataVersion : String + - eventTime : String + - eventType : String + - id : String + - subject : String + - topic : String + + MessageHeader() + + getData() : Object + + getDataVersion() : String + + getEventTime() : String + + getEventType() : String + + getId() : String + + getSubject() : String + + getTopic() : String + + setData(data : Object) + + setDataVersion(dataVersion : String) + + setEventTime(eventTime : String) + + setEventType(eventType : String) + + setId(id : String) + + setSubject(subject : String) + + setTopic(topic : String) + } + class MessageReference { + - dataFileName : String + - dataLocation : String + + MessageReference() + + MessageReference(dataLocation : String, dataFileName : String) + + getDataFileName() : String + + getDataLocation() : String + + setDataFileName(dataFileName : String) + + setDataLocation(dataLocation : String) + } + class UsageCostDetail { + - callCost : double + - dataCost : double + - userId : String + + UsageCostDetail() + + getCallCost() : double + + getDataCost() : double + + getUserId() : String + + setCallCost(callCost : double) + + setDataCost(dataCost : double) + + setUserId(userId : String) + } + class UsageDetail { + - data : int + - duration : int + - userId : String + + UsageDetail() + + getData() : int + + getDuration() : int + + getUserId() : String + + setData(data : int) + + setDuration(duration : int) + + setUserId(userId : String) + } +} +package com.iluwatar.claimcheckpattern.utility { + class EventHandlerUtility { + - customEventClient : EventGridPublisherClient + + EventHandlerUtility() + + EventHandlerUtility(customEventClient : EventGridPublisherClient) + + publishEvent(customEvent : T, logger : Logger) + } + class MessageHandlerUtility { + - blobServiceClient : BlobServiceClient + + MessageHandlerUtility() + + MessageHandlerUtility(blobServiceClient : BlobServiceClient) + + dropToPersistantStorage(message : Message, logger : Logger) + + readFromPersistantStorage(messageReference : MessageReference, logger : Logger) : Message + } +} +package com.iluwatar.claimcheckpattern.consumer.callcostprocessor.functions { + class UsageCostProcessorFunction { + - messageHandlerUtilityForUsageCostDetail : MessageHandlerUtility + - messageHandlerUtilityForUsageDetail : MessageHandlerUtility + + UsageCostProcessorFunction() + + UsageCostProcessorFunction(messageHandlerUtilityForUsageDetail : MessageHandlerUtility, messageHandlerUtilityForUsageCostDetail : MessageHandlerUtility) + - calculateUsageCostDetails(usageDetailsList : List) : List + + run(request : HttpRequestMessage>, context : ExecutionContext) : HttpResponseMessage + } +} +UsageCostProcessorFunction --> "-messageHandlerUtilityForUsageDetail" MessageHandlerUtility +Message --> "-messageBody" MessageBody +UsageDetailPublisherFunction --> "-eventHandlerUtility" EventHandlerUtility +Builder ..+ HttpResponseMessage +UsageDetailPublisherFunction --> "-messageHandlerUtility" MessageHandlerUtility +Message --> "-messageHeader" MessageHeader +@enduml \ No newline at end of file diff --git a/cloud-claim-check-pattern/call-usage-app/host.json b/cloud-claim-check-pattern/call-usage-app/host.json new file mode 100644 index 000000000..4ac89572d --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/host.json @@ -0,0 +1,7 @@ +{ + "version": "2.0", + "extensionBundle": { + "id": "Microsoft.Azure.Functions.ExtensionBundle", + "version": "[1.*, 2.0.0)" + } +} \ No newline at end of file diff --git a/cloud-claim-check-pattern/call-usage-app/pom.xml b/cloud-claim-check-pattern/call-usage-app/pom.xml new file mode 100644 index 000000000..a1bc7fc10 --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/pom.xml @@ -0,0 +1,150 @@ + + + + 4.0.0 + + + + com.iluwatar + claim-check-pattern + 1.25.0-SNAPSHOT + + + call-usage-app + call-usage-app + jar + + + UTF-8 + 1.14.0 + 1.4.2 + CallUsageApp + + + + + + com.azure + azure-sdk-bom + 1.0.4 + pom + import + + + + + + + com.microsoft.azure.functions + azure-functions-java-library + ${azure.functions.java.library.version} + + + + com.azure + azure-messaging-eventgrid + + + + com.azure + azure-storage-blob + 12.13.0 + + + + org.slf4j + slf4j-simple + test + + + + + org.mockito + mockito-core + test + + + + + + + + + com.microsoft.azure + azure-functions-maven-plugin + ${azure.functions.maven.plugin.version} + + + ${functionAppName} + + java-functions-group + + java-functions-app-service-plan + + + westus + + + + + + + + + windows + 11 + + + + FUNCTIONS_EXTENSION_VERSION + ~3 + + + + + + package-functions + + package + + + + + + + maven-clean-plugin + 3.1.0 + + + + obj + + + + + + + diff --git a/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/consumer/callcostprocessor/functions/UsageCostProcessorFunction.java b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/consumer/callcostprocessor/functions/UsageCostProcessorFunction.java new file mode 100644 index 000000000..652095727 --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/consumer/callcostprocessor/functions/UsageCostProcessorFunction.java @@ -0,0 +1,168 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.consumer.callcostprocessor.functions; + +import com.azure.core.util.BinaryData; +import com.azure.core.util.serializer.TypeReference; +import com.azure.messaging.eventgrid.EventGridEvent; +import com.azure.messaging.eventgrid.systemevents.SubscriptionValidationEventData; +import com.azure.messaging.eventgrid.systemevents.SubscriptionValidationResponse; +import com.iluwatar.claimcheckpattern.domain.Message; +import com.iluwatar.claimcheckpattern.domain.MessageBody; +import com.iluwatar.claimcheckpattern.domain.MessageHeader; +import com.iluwatar.claimcheckpattern.domain.MessageReference; +import com.iluwatar.claimcheckpattern.domain.UsageCostDetail; +import com.iluwatar.claimcheckpattern.domain.UsageDetail; +import com.iluwatar.claimcheckpattern.utility.MessageHandlerUtility; +import com.microsoft.azure.functions.ExecutionContext; +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * Azure Functions with HTTP Trigger. + * This is Consumer class. + */ +public class UsageCostProcessorFunction { + + private MessageHandlerUtility messageHandlerUtilityForUsageDetail; + private MessageHandlerUtility messageHandlerUtilityForUsageCostDetail; + + public UsageCostProcessorFunction() { + this.messageHandlerUtilityForUsageDetail = new MessageHandlerUtility<>(); + this.messageHandlerUtilityForUsageCostDetail = new MessageHandlerUtility<>(); + } + + public UsageCostProcessorFunction( + MessageHandlerUtility messageHandlerUtilityForUsageDetail, + MessageHandlerUtility messageHandlerUtilityForUsageCostDetail) { + this.messageHandlerUtilityForUsageDetail = messageHandlerUtilityForUsageDetail; + this.messageHandlerUtilityForUsageCostDetail = messageHandlerUtilityForUsageCostDetail; + } + + /** + * Azure function which gets triggered when event grid event send event to it. + * After receiving event, it read input file from blob storage, calculate call cost details. + * It creates new message with cost details and drop message to blob storage. + * @param request represents HttpRequestMessage + * @param context represents ExecutionContext + * @return HttpResponseMessage + */ + @FunctionName("UsageCostProcessorFunction") + public HttpResponseMessage run(@HttpTrigger(name = "req", methods = { HttpMethod.GET, + HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) + HttpRequestMessage> request, + final ExecutionContext context) { + try { + var eventGridEvents = EventGridEvent.fromString(request.getBody().get()); + for (var eventGridEvent : eventGridEvents) { + // Handle system events + if (eventGridEvent.getEventType() + .equals("Microsoft.EventGrid.SubscriptionValidationEvent")) { + SubscriptionValidationEventData subscriptionValidationEventData = eventGridEvent.getData() + .toObject(SubscriptionValidationEventData.class); + // Handle the subscription validation event + var responseData = new SubscriptionValidationResponse(); + responseData.setValidationResponse(subscriptionValidationEventData.getValidationCode()); + return request.createResponseBuilder(HttpStatus.OK).body(responseData).build(); + + } else if (eventGridEvent.getEventType().equals("UsageDetail")) { + // Get message header and reference + var messageReference = eventGridEvent.getData() + .toObject(MessageReference.class); + + // Read message from persistent storage + var message = this.messageHandlerUtilityForUsageDetail + .readFromPersistantStorage(messageReference, context.getLogger()); + + // Get Data and generate cost details + List usageDetailsList = BinaryData.fromObject( + message.getMessageBody().getData()) + .toObject(new TypeReference<>() { + }); + var usageCostDetailsList = calculateUsageCostDetails(usageDetailsList); + + // Create message body + var newMessageBody = new MessageBody(); + newMessageBody.setData(usageCostDetailsList); + + // Create message header + var newMessageReference = new MessageReference("callusageapp", + eventGridEvent.getId() + "/output.json"); + var newMessageHeader = new MessageHeader(); + newMessageHeader.setId(eventGridEvent.getId()); + newMessageHeader.setSubject("UsageCostProcessor"); + newMessageHeader.setTopic(""); + newMessageHeader.setEventType("UsageCostDetail"); + newMessageHeader.setEventTime(OffsetDateTime.now().toString()); + newMessageHeader.setData(newMessageReference); + newMessageHeader.setDataVersion("v1.0"); + + // Create entire message + var newMessage = new Message(); + newMessage.setMessageHeader(newMessageHeader); + newMessage.setMessageBody(newMessageBody); + + // Drop data to persistent storage + this.messageHandlerUtilityForUsageCostDetail.dropToPersistantStorage(newMessage, + context.getLogger()); + + context.getLogger().info("Message is dropped successfully"); + return request.createResponseBuilder(HttpStatus.OK) + .body("Message is dropped successfully").build(); + } + } + } catch (Exception e) { + context.getLogger().warning(e.getMessage()); + } + + return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR).body(null).build(); + } + + private List calculateUsageCostDetails(List usageDetailsList) { + if (usageDetailsList == null) { + return null; + } + var usageCostDetailsList = new ArrayList(); + + usageDetailsList.forEach(usageDetail -> { + var usageCostDetail = new UsageCostDetail(); + usageCostDetail.setUserId(usageDetail.getUserId()); + usageCostDetail.setCallCost(usageDetail.getDuration() * 0.30); // 0.30₹ per minute + usageCostDetail.setDataCost(usageDetail.getData() * 0.20); // 0.20₹ per MB + + usageCostDetailsList.add(usageCostDetail); + }); + + return usageCostDetailsList; + } +} diff --git a/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/Message.java b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/Message.java new file mode 100644 index 000000000..d85653dcd --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/Message.java @@ -0,0 +1,43 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.domain; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * It is the message which gets dropped or read by Producer or Consumer Azure functions. + * It is stored in the json format. + * @param represents UsageDetail or UsageCostDetail + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Message { + private MessageHeader messageHeader; + + private MessageBody messageBody; + +} \ No newline at end of file diff --git a/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/MessageBody.java b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/MessageBody.java new file mode 100644 index 000000000..e8284e04e --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/MessageBody.java @@ -0,0 +1,43 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.domain; + +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * It is message body of the message. + * It stores actual data in our case UsageCostDetail or UsageDetail. + * @param represents UsageDetail or UsageCostDetail + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MessageBody { + + private List data; + +} diff --git a/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/MessageHeader.java b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/MessageHeader.java new file mode 100644 index 000000000..71e897ca9 --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/MessageHeader.java @@ -0,0 +1,47 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.domain; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * This is message header or event which is sent to Event Grid. + * Its structure is same as Azure Event Grid Event Class. + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MessageHeader { + + private String id; + private String subject; + private String topic; + private String eventType; + private String eventTime; + private Object data; + private String dataVersion; + +} \ No newline at end of file diff --git a/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/MessageReference.java b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/MessageReference.java new file mode 100644 index 000000000..9eab15a3a --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/MessageReference.java @@ -0,0 +1,45 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.domain; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * This is claim/message reference class. + * It contains the information about data where it is stored in persistent storage + * and file name. + * dataLocation is blob storage container name. + * dataFileName is file name in above container. + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MessageReference { + + private String dataLocation; + private String dataFileName; + +} diff --git a/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/UsageCostDetail.java b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/UsageCostDetail.java new file mode 100644 index 000000000..8930ea3f5 --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/UsageCostDetail.java @@ -0,0 +1,43 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.domain; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * This is call cost details class. + * It stores userId of the caller, call duration cost and data cost. + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UsageCostDetail { + + private String userId; + private double callCost; + private double dataCost; + +} diff --git a/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/UsageDetail.java b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/UsageDetail.java new file mode 100644 index 000000000..c8f0395db --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/domain/UsageDetail.java @@ -0,0 +1,44 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.domain; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * This is call usage detail calls. + * It stores userId of the caller, call duration and data used. + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UsageDetail { + + private String userId; + + private int duration; + + private int data; +} diff --git a/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/producer/calldetails/functions/UsageDetailPublisherFunction.java b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/producer/calldetails/functions/UsageDetailPublisherFunction.java new file mode 100644 index 000000000..2f58f8f48 --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/producer/calldetails/functions/UsageDetailPublisherFunction.java @@ -0,0 +1,146 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.producer.calldetails.functions; + +import com.azure.messaging.eventgrid.EventGridEvent; +import com.azure.messaging.eventgrid.systemevents.SubscriptionValidationEventData; +import com.azure.messaging.eventgrid.systemevents.SubscriptionValidationResponse; +import com.iluwatar.claimcheckpattern.domain.Message; +import com.iluwatar.claimcheckpattern.domain.MessageBody; +import com.iluwatar.claimcheckpattern.domain.MessageHeader; +import com.iluwatar.claimcheckpattern.domain.MessageReference; +import com.iluwatar.claimcheckpattern.domain.UsageDetail; +import com.iluwatar.claimcheckpattern.utility.EventHandlerUtility; +import com.iluwatar.claimcheckpattern.utility.MessageHandlerUtility; +import com.microsoft.azure.functions.ExecutionContext; +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Random; +import java.util.UUID; + +/** + * Azure Functions with HTTP Trigger. + * This is Producer class. + */ +public class UsageDetailPublisherFunction { + + private MessageHandlerUtility messageHandlerUtility; + private EventHandlerUtility eventHandlerUtility; + + public UsageDetailPublisherFunction() { + this.messageHandlerUtility = new MessageHandlerUtility<>(); + this.eventHandlerUtility = new EventHandlerUtility<>(); + } + + public UsageDetailPublisherFunction(MessageHandlerUtility messageHandlerUtility, + EventHandlerUtility eventHandlerUtility) { + this.messageHandlerUtility = messageHandlerUtility; + this.eventHandlerUtility = eventHandlerUtility; + } + + /** + * Azure function which create message, drop it in persistent storage + * and publish the event to Event Grid topic. + * @param request represents HttpRequestMessage + * @param context represents ExecutionContext + * @return HttpResponseMessage + */ + @FunctionName("UsageDetailPublisherFunction") + public HttpResponseMessage run(@HttpTrigger(name = "req", methods = { + HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) + HttpRequestMessage> request, + final ExecutionContext context) { + try { + + var eventGridEvents = EventGridEvent.fromString(request.getBody().get()); + + for (EventGridEvent eventGridEvent : eventGridEvents) { + // Handle system events + if (eventGridEvent.getEventType() + .equals("Microsoft.EventGrid.SubscriptionValidationEvent")) { + SubscriptionValidationEventData subscriptionValidationEventData = eventGridEvent.getData() + .toObject(SubscriptionValidationEventData.class); + // Handle the subscription validation event + var responseData = new SubscriptionValidationResponse(); + responseData.setValidationResponse(subscriptionValidationEventData.getValidationCode()); + return request.createResponseBuilder(HttpStatus.OK).body(responseData).build(); + + } else if (eventGridEvent.getEventType().equals("UsageDetail")) { + // Create message body + var messageBody = new MessageBody(); + var usageDetailsList = new ArrayList(); + var random = new Random(); + for (int i = 0; i < 51; i++) { + var usageDetail = new UsageDetail(); + usageDetail.setUserId("userId" + i); + usageDetail.setData(random.nextInt(500)); + usageDetail.setDuration(random.nextInt(500)); + + usageDetailsList.add(usageDetail); + } + messageBody.setData(usageDetailsList); + + // Create message header + var messageHeader = new MessageHeader(); + messageHeader.setId(UUID.randomUUID().toString()); + messageHeader.setSubject("UsageDetailPublisher"); + messageHeader.setTopic("usagecostprocessorfunction-topic"); + messageHeader.setEventType("UsageDetail"); + messageHeader.setEventTime(OffsetDateTime.now().toString()); + var messageReference = new MessageReference("callusageapp", + messageHeader.getId() + "/input.json"); + messageHeader.setData(messageReference); + messageHeader.setDataVersion("v1.0"); + + // Create entire message + var message = new Message(); + message.setMessageHeader(messageHeader); + message.setMessageBody(messageBody); + + // Drop data to persistent storage + this.messageHandlerUtility.dropToPersistantStorage(message, context.getLogger()); + + // Publish event to event grid topic + eventHandlerUtility.publishEvent(messageHeader, context.getLogger()); + + context.getLogger().info("Message is dropped and event is published successfully"); + return request.createResponseBuilder(HttpStatus.OK).body(message).build(); + } + } + } catch (Exception e) { + context.getLogger().warning(e.getMessage()); + } + + return request.createResponseBuilder(HttpStatus.OK).body(null).build(); + } +} diff --git a/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/utility/EventHandlerUtility.java b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/utility/EventHandlerUtility.java new file mode 100644 index 000000000..c037db10d --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/utility/EventHandlerUtility.java @@ -0,0 +1,66 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.utility; + +import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.util.BinaryData; +import com.azure.messaging.eventgrid.EventGridPublisherClient; +import com.azure.messaging.eventgrid.EventGridPublisherClientBuilder; +import java.util.logging.Logger; + +/** + * This class is event publisher utility which published message header to Event Grid topic. + * @param represents UsageDetail or UsageCostDetail + */ +public class EventHandlerUtility { + + private EventGridPublisherClient customEventClient; + + /** Default constructor. + */ + public EventHandlerUtility() { + this.customEventClient = new EventGridPublisherClientBuilder() + .endpoint(System.getenv("EventGridURL")) + .credential(new AzureKeyCredential(System.getenv("EventGridKey"))) + .buildCustomEventPublisherClient(); + } + + /** + Parameterized constructor. + */ + public EventHandlerUtility(EventGridPublisherClient customEventClient) { + this.customEventClient = customEventClient; + } + + /** + Method for publishing event to Event Grid Topic. + */ + public void publishEvent(T customEvent, Logger logger) { + try { + customEventClient.sendEvent(BinaryData.fromObject(customEvent)); + } catch (Exception e) { + logger.info(e.getMessage()); + } + } +} diff --git a/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/utility/MessageHandlerUtility.java b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/utility/MessageHandlerUtility.java new file mode 100644 index 000000000..40aac8ab9 --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/main/java/com/iluwatar/claimcheckpattern/utility/MessageHandlerUtility.java @@ -0,0 +1,127 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.utility; + +import com.azure.core.util.BinaryData; +import com.azure.core.util.serializer.TypeReference; +import com.azure.storage.blob.BlobClient; +import com.azure.storage.blob.BlobContainerClient; +import com.azure.storage.blob.BlobServiceClient; +import com.azure.storage.blob.BlobServiceClientBuilder; +import com.iluwatar.claimcheckpattern.domain.Message; +import com.iluwatar.claimcheckpattern.domain.MessageReference; +import java.util.logging.Logger; + +/** + * This class read and drop message from Azure blob storage. + * @param represents UsageDetail or UsageCostDetail + */ +public class MessageHandlerUtility { + + private BlobServiceClient blobServiceClient; + + /** + * Parameterized constructor. + * @param blobServiceClient represents BlobServiceClient + */ + public MessageHandlerUtility(BlobServiceClient blobServiceClient) { + this.blobServiceClient = blobServiceClient; + } + + /** + * Default constructor. + */ + public MessageHandlerUtility() { + // Create a BlobServiceClient object which will be used to create a container + // client + this.blobServiceClient = new BlobServiceClientBuilder() + .connectionString(System.getenv("BlobStorageConnectionString")).buildClient(); + + } + + /** + * Read message from blob storage. + * @param messageReference represents MessageReference + * @param logger represents Logger + * @return Message + */ + public Message readFromPersistantStorage(MessageReference messageReference, Logger logger) { + Message message = null; + try { + + // Get container name from message reference + String containerName = messageReference.getDataLocation(); + + // Get blob name from message reference + String blobName = messageReference.getDataFileName(); + + // Get container client + BlobContainerClient containerClient = blobServiceClient.getBlobContainerClient(containerName); + + // Get a reference to a blob + BlobClient blobClient = containerClient.getBlobClient(blobName); + + // download the blob + message = blobClient.downloadContent().toObject(new TypeReference>() { + }); + } catch (Exception e) { + logger.info(e.getMessage()); + } + return message; + + } + + /** + * Drop message to blob storage. + * @param message represents Message + * @param logger represents Logger + */ + public void dropToPersistantStorage(Message message, Logger logger) { + try { + + // Get message reference + MessageReference messageReference = (MessageReference) message.getMessageHeader().getData(); + + // Create a unique name for the container + String containerName = messageReference.getDataLocation(); + + // Create the container and return a container client object + BlobContainerClient containerClient = this.blobServiceClient + .getBlobContainerClient(containerName); + if (!containerClient.exists()) { + containerClient.create(); + } + + // Get a reference to a blob + BlobClient blobClient = containerClient.getBlobClient(messageReference.getDataFileName()); + + // Upload the blob + blobClient.upload(BinaryData.fromObject(message)); + } catch (Exception e) { + logger.info(e.getMessage()); + } + + } + +} diff --git a/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/HttpResponseMessageMock.java b/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/HttpResponseMessageMock.java new file mode 100644 index 000000000..94cb48240 --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/HttpResponseMessageMock.java @@ -0,0 +1,105 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern; + +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.HttpStatusType; +import java.util.HashMap; +import java.util.Map; + +/** + * The mock for HttpResponseMessage, can be used in unit tests to verify if the + * returned response by HTTP trigger function is correct or not. + */ +public class HttpResponseMessageMock implements HttpResponseMessage { + private int httpStatusCode; + private HttpStatusType httpStatus; + private Object body; + private Map headers; + + public HttpResponseMessageMock(HttpStatusType status, Map headers, Object body) { + this.httpStatus = status; + this.httpStatusCode = status.value(); + this.headers = headers; + this.body = body; + } + + @Override + public HttpStatusType getStatus() { + return this.httpStatus; + } + + @Override + public int getStatusCode() { + return httpStatusCode; + } + + @Override + public String getHeader(String key) { + return this.headers.get(key); + } + + @Override + public Object getBody() { + return this.body; + } + + public static class HttpResponseMessageBuilderMock implements HttpResponseMessage.Builder { + private Object body; + private int httpStatusCode; + private Map headers = new HashMap<>(); + private HttpStatusType httpStatus; + + public Builder status(HttpStatus status) { + this.httpStatusCode = status.value(); + this.httpStatus = status; + return this; + } + + @Override + public Builder status(HttpStatusType httpStatusType) { + this.httpStatusCode = httpStatusType.value(); + this.httpStatus = httpStatusType; + return this; + } + + @Override + public HttpResponseMessage.Builder header(String key, String value) { + this.headers.put(key, value); + return this; + } + + @Override + public HttpResponseMessage.Builder body(Object body) { + this.body = body; + return this; + } + + @Override + public HttpResponseMessage build() { + return new HttpResponseMessageMock(this.httpStatus, this.headers, this.body); + } + } +} diff --git a/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/consumer/callcostprocessor/functions/UsageCostProcessorFunctionTest.java b/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/consumer/callcostprocessor/functions/UsageCostProcessorFunctionTest.java new file mode 100644 index 000000000..940a39af7 --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/consumer/callcostprocessor/functions/UsageCostProcessorFunctionTest.java @@ -0,0 +1,181 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.consumer.callcostprocessor.functions; + +import com.iluwatar.claimcheckpattern.HttpResponseMessageMock; +import com.iluwatar.claimcheckpattern.domain.Message; +import com.iluwatar.claimcheckpattern.domain.MessageBody; +import com.iluwatar.claimcheckpattern.domain.MessageHeader; +import com.iluwatar.claimcheckpattern.domain.MessageReference; +import com.iluwatar.claimcheckpattern.domain.UsageCostDetail; +import com.iluwatar.claimcheckpattern.domain.UsageDetail; +import com.iluwatar.claimcheckpattern.utility.MessageHandlerUtility; +import com.microsoft.azure.functions.ExecutionContext; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.stubbing.Answer; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.OffsetDateTime; +import java.util.*; +import java.util.logging.Logger; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +/** + * Unit test for Function class. + */ +@ExtendWith(MockitoExtension.class) +public class UsageCostProcessorFunctionTest { + + @Mock + MessageHandlerUtility mockMessageHandlerUtilityForUsageADetail; + @Mock + MessageHandlerUtility mockMessageHandlerUtilityForUsageCostDetail; + @Mock + ExecutionContext context; + + Message messageToDrop; + Message messageToRead; + MessageReference messageReference; + @InjectMocks + UsageCostProcessorFunction usageCostProcessorFunction; + + @BeforeEach + public void setUp() { + var messageBodyUsageDetail = new MessageBody(); + var usageDetailsList = new ArrayList(); + + var messageBodyUsageCostDetail = new MessageBody(); + var usageCostDetailsList = new ArrayList(); + for (int i = 0; i < 2; i++) { + var usageDetail = new UsageDetail(); + usageDetail.setUserId("userId" + i); + usageDetail.setData(i + 1); + usageDetail.setDuration(i + 1); + usageDetailsList.add(usageDetail); + + var usageCostDetail = new UsageCostDetail(); + usageCostDetail.setUserId(usageDetail.getUserId()); + usageCostDetail.setDataCost(usageDetail.getData() * 0.20); + usageCostDetail.setCallCost(usageDetail.getDuration() * 0.30); + usageCostDetailsList.add(usageCostDetail); + } + messageBodyUsageDetail.setData(usageDetailsList); + messageBodyUsageCostDetail.setData(usageCostDetailsList); + + // Create message header + var messageHeader = new MessageHeader(); + messageHeader.setId(UUID.randomUUID().toString()); + messageHeader.setSubject("UsageDetailPublisher"); + messageHeader.setTopic("usagecostprocessorfunction-topic"); + messageHeader.setEventType("UsageDetail"); + messageHeader.setEventTime(OffsetDateTime.now().toString()); + this.messageReference = new MessageReference("callusageapp", "d8284456-dfff-4bd4-9cef-ea99f70f4835/input.json"); + messageHeader.setData(messageReference); + messageHeader.setDataVersion("v1.0"); + + // Create entire message + messageToRead = new Message<>(); + messageToRead.setMessageHeader(messageHeader); + messageToRead.setMessageBody(messageBodyUsageDetail); + + messageToDrop = new Message<>(); + messageToDrop.setMessageHeader(messageHeader); + messageToDrop.setMessageBody(messageBodyUsageCostDetail); + + } + + /** + * Unit test for HttpTriggerJava method. + */ + @Test + public void shouldTriggerHttpAzureFunctionJavaWithSubscriptionValidationEventType() throws Exception { + + // Setup + @SuppressWarnings("unchecked") + final HttpRequestMessage> req = mock(HttpRequestMessage.class); + String fileAbsolutePath = getClass().getResource("/subscriptionValidationEvent.json").getPath() + .replaceAll("%20", " "), jsonBody = Files.readString(Paths.get(fileAbsolutePath)).replaceAll("\n", " "); + doReturn(Optional.of(jsonBody)).when(req).getBody(); + doAnswer(new Answer() { + @Override + public HttpResponseMessage.Builder answer(InvocationOnMock invocation) { + HttpStatus status = (HttpStatus) invocation.getArguments()[0]; + return new HttpResponseMessageMock.HttpResponseMessageBuilderMock().status(status); + } + }).when(req).createResponseBuilder(any(HttpStatus.class)); + + final ExecutionContext context = mock(ExecutionContext.class); + + // Invoke + final HttpResponseMessage ret = this.usageCostProcessorFunction.run(req, context); + + // Verify + assertEquals(ret.getStatus(), HttpStatus.OK); + } + + @Test + public void shouldTriggerHttpAzureFunctionJavaWithUsageDetailEventType() throws Exception { + // Setup + @SuppressWarnings("unchecked") + final HttpRequestMessage> req = mock(HttpRequestMessage.class); + String fileAbsolutePath = getClass().getResource("/usageDetailEvent.json").getPath().replaceAll("%20", " "), + jsonBody = Files.readString(Paths.get(fileAbsolutePath)).replaceAll("\n", " "); + doReturn(Optional.of(jsonBody)).when(req).getBody(); + doReturn(Logger.getGlobal()).when(context).getLogger(); + + when(this.mockMessageHandlerUtilityForUsageADetail.readFromPersistantStorage(any(MessageReference.class), + eq(Logger.getGlobal()))).thenReturn(messageToRead); + doAnswer(new Answer() { + @Override + public HttpResponseMessage.Builder answer(InvocationOnMock invocation) { + HttpStatus status = (HttpStatus) invocation.getArguments()[0]; + return new HttpResponseMessageMock.HttpResponseMessageBuilderMock().status(status); + } + }).when(req).createResponseBuilder(any(HttpStatus.class)); + + assertNotNull(this.mockMessageHandlerUtilityForUsageADetail); + assertEquals(this.messageToRead, this.mockMessageHandlerUtilityForUsageADetail + .readFromPersistantStorage(this.messageReference, Logger.getGlobal())); + + // Invoke + final HttpResponseMessage ret = this.usageCostProcessorFunction.run(req, context); + + // Verify + assertEquals(HttpStatus.OK, ret.getStatus()); + assertEquals("Message is dropped successfully", ret.getBody()); + } + +} diff --git a/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/producer/calldetails/functions/UsageDetailPublisherFunctionTest.java b/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/producer/calldetails/functions/UsageDetailPublisherFunctionTest.java new file mode 100644 index 000000000..60083a81b --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/producer/calldetails/functions/UsageDetailPublisherFunctionTest.java @@ -0,0 +1,119 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.producer.calldetails.functions; + +import com.iluwatar.claimcheckpattern.HttpResponseMessageMock; +import com.iluwatar.claimcheckpattern.domain.MessageHeader; +import com.iluwatar.claimcheckpattern.domain.UsageDetail; +import com.iluwatar.claimcheckpattern.utility.EventHandlerUtility; +import com.iluwatar.claimcheckpattern.utility.MessageHandlerUtility; +import com.microsoft.azure.functions.ExecutionContext; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.stubbing.Answer; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; +import java.util.logging.Logger; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +/** + * Unit test for Function class. + */ +@ExtendWith(MockitoExtension.class) +public class UsageDetailPublisherFunctionTest { + @Mock + MessageHandlerUtility mockMessageHandlerUtility; + @Mock + EventHandlerUtility mockEventHandlerUtility; + + @InjectMocks + UsageDetailPublisherFunction usageDetailPublisherFunction; + + /** + * Unit test for HttpTriggerJava method. + */ + @Test + public void shouldTriggerHttpAzureFunctionJavaWithSubscriptionValidationEventType() throws Exception { + + // Setup + @SuppressWarnings("unchecked") + final HttpRequestMessage> req = mock(HttpRequestMessage.class); + String fileAbsolutePath = getClass().getResource("/subscriptionValidationEvent.json").getPath() + .replaceAll("%20", " "), jsonBody = Files.readString(Paths.get(fileAbsolutePath)).replaceAll("\n", " "); + doReturn(Optional.of(jsonBody)).when(req).getBody(); + doAnswer(new Answer() { + @Override + public HttpResponseMessage.Builder answer(InvocationOnMock invocation) { + HttpStatus status = (HttpStatus) invocation.getArguments()[0]; + return new HttpResponseMessageMock.HttpResponseMessageBuilderMock().status(status); + } + }).when(req).createResponseBuilder(any(HttpStatus.class)); + + final ExecutionContext context = mock(ExecutionContext.class); + + // Invoke + final HttpResponseMessage ret = this.usageDetailPublisherFunction.run(req, context); + + // Verify + assertEquals(ret.getStatus(), HttpStatus.OK); + } + + @Test + public void shouldTriggerHttpAzureFunctionJavaWithUsageDetailEventType() throws Exception { + + // Setup + @SuppressWarnings("unchecked") + final HttpRequestMessage> req = mock(HttpRequestMessage.class); + String fileAbsolutePath = getClass().getResource("/usageDetailEvent.json").getPath().replaceAll("%20", " "), + jsonBody = Files.readString(Paths.get(fileAbsolutePath)).replaceAll("\n", " "); + doReturn(Optional.of(jsonBody)).when(req).getBody(); + doAnswer(new Answer() { + @Override + public HttpResponseMessage.Builder answer(InvocationOnMock invocation) { + HttpStatus status = (HttpStatus) invocation.getArguments()[0]; + return new HttpResponseMessageMock.HttpResponseMessageBuilderMock().status(status); + } + }).when(req).createResponseBuilder(any(HttpStatus.class)); + + final ExecutionContext context = mock(ExecutionContext.class); + doReturn(Logger.getGlobal()).when(context).getLogger(); + + // Invoke + final HttpResponseMessage ret = this.usageDetailPublisherFunction.run(req, context); + + // Verify + assertEquals(ret.getStatus(), HttpStatus.OK); + } + +} diff --git a/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/utility/EventHandlerUtilityTest.java b/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/utility/EventHandlerUtilityTest.java new file mode 100644 index 000000000..f16f60f6d --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/utility/EventHandlerUtilityTest.java @@ -0,0 +1,70 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.utility; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import com.azure.core.util.BinaryData; +import com.azure.messaging.eventgrid.EventGridPublisherClient; +import com.iluwatar.claimcheckpattern.domain.Message; +import com.iluwatar.claimcheckpattern.domain.UsageDetail; +import java.util.logging.Logger; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class EventHandlerUtilityTest { + + @Mock + EventGridPublisherClient mockCustomEventClient; + + @InjectMocks + EventHandlerUtility> eventHandlerUtility; + + @BeforeEach + public void setUp() { + + System.setProperty("EventGridURL", "https://www.dummyEndpoint.com/api/events"); + System.setProperty("EventGridKey", "EventGridURL"); + } + + @Test + void shouldPublishEvent() { + doNothing().when(mockCustomEventClient).sendEvent(any(BinaryData.class)); + eventHandlerUtility.publishEvent(null, Logger.getLogger("logger")); + verify(mockCustomEventClient, times(1)).sendEvent(any(BinaryData.class)); + + } + + @Test + void shouldPublishEventWithNullLogger() { + eventHandlerUtility.publishEvent(null, null); + verify(mockCustomEventClient, times(1)).sendEvent(any(BinaryData.class)); + } +} diff --git a/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/utility/MessageHandlerUtilityTest.java b/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/utility/MessageHandlerUtilityTest.java new file mode 100644 index 000000000..4faab105d --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/test/java/com/iluwatar/claimcheckpattern/utility/MessageHandlerUtilityTest.java @@ -0,0 +1,114 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.claimcheckpattern.utility; + +import com.azure.storage.blob.BlobClient; +import com.azure.storage.blob.BlobContainerClient; +import com.azure.storage.blob.BlobServiceClient; +import com.iluwatar.claimcheckpattern.domain.*; +import com.iluwatar.claimcheckpattern.utility.MessageHandlerUtility; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.UUID; +import java.util.logging.Logger; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class MessageHandlerUtilityTest { + @Mock + private BlobClient mockBlobClient; + + @Mock + private BlobContainerClient mockContainerClient; + + @Mock + private BlobServiceClient mockBlobServiceClient; + + @InjectMocks + private MessageHandlerUtility messageHandlerUtility; + + private Message messageToPublish; + private MessageReference messageReference; + + @BeforeEach + public void setUp() { + System.setProperty("BlobStorageConnectionString", "https://www.dummyEndpoint.com/api/blobs"); + + var messageBody = new MessageBody(); + var usageDetailsList = new ArrayList(); + var random = new Random(); + for (int i = 0; i < 51; i++) { + var usageDetail = new UsageDetail(); + usageDetail.setUserId("userId" + i); + usageDetail.setData(random.nextInt(500)); + usageDetail.setDuration(random.nextInt(500)); + + usageDetailsList.add(usageDetail); + } + messageBody.setData(usageDetailsList); + + // Create message header + var messageHeader = new MessageHeader(); + messageHeader.setId(UUID.randomUUID().toString()); + messageHeader.setSubject("UsageDetailPublisher"); + messageHeader.setTopic("usagecostprocessorfunction-topic"); + messageHeader.setEventType("UsageDetail"); + messageHeader.setEventTime(OffsetDateTime.now().toString()); + this.messageReference = new MessageReference("callusageapp", messageHeader.getId() + "/input.json"); + messageHeader.setData(messageReference); + messageHeader.setDataVersion("v1.0"); + + // Create entire message + this.messageToPublish = new Message<>(); + this.messageToPublish.setMessageHeader(messageHeader); + this.messageToPublish.setMessageBody(messageBody); + + when(mockContainerClient.getBlobClient(anyString())).thenReturn(mockBlobClient); + when(mockBlobServiceClient.getBlobContainerClient(anyString())).thenReturn(mockContainerClient); + } + + @Test + void shouldDropMessageToPersistantStorage() { + messageHandlerUtility.dropToPersistantStorage(messageToPublish, Logger.getLogger("logger")); + verify(mockBlobServiceClient, times(1)).getBlobContainerClient(anyString()); + // verify(mockContainerClient, times(0)).exists(); + } + + @Test + void shouldReadMessageFromPersistantStorage() { + + messageHandlerUtility.readFromPersistantStorage(messageReference, Logger.getLogger("logger")); + verify(mockBlobServiceClient, times(1)).getBlobContainerClient(anyString()); + } +} diff --git a/cloud-claim-check-pattern/call-usage-app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/cloud-claim-check-pattern/call-usage-app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 000000000..ca6ee9cea --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file diff --git a/cloud-claim-check-pattern/call-usage-app/src/test/resources/subscriptionValidationEvent.json b/cloud-claim-check-pattern/call-usage-app/src/test/resources/subscriptionValidationEvent.json new file mode 100644 index 000000000..52bd6ee6a --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/test/resources/subscriptionValidationEvent.json @@ -0,0 +1,15 @@ +[ + { + "data": { + "validationCode": "C12F266E-79D9-4C0A-9922-5EF6201A34C2", + "validationUrl": "https://rp-centralindia.eventgrid.azure.net:553/eventsubscriptions/usagedetailpublisherfunction-subscription/validate?idu003dC12F266E-79D9-4C0A-9922-5EF6201A34C2u0026tu003d2021-10-26T08:10:52.4999377Zu0026apiVersionu003d2020-10-15-previewu0026tokenu003d30kEVoL8rAOWzQv0buurhrKnbP%2bGMtHObbA%2bax6wb4Y%3d" + }, + "dataVersion": "2", + "eventTime": "2021-10-26T08:10:52.4999377Z", + "eventType": "Microsoft.EventGrid.SubscriptionValidationEvent", + "id": "e2a8466b-3dc0-46b7-bb7d-b999e51a2848", + "metadataVersion": "1", + "subject": "", + "topic": "/subscriptions/0fef643d-a6b1-48f9-a256-53fbd0d22f48/resourceGroups/resource-group-ccp/providers/Microsoft.EventGrid/domains/event-grid-domains-ccp/topics/usagedetailpublisherfunction-topic" + } +] diff --git a/cloud-claim-check-pattern/call-usage-app/src/test/resources/usageDetailEvent.json b/cloud-claim-check-pattern/call-usage-app/src/test/resources/usageDetailEvent.json new file mode 100644 index 000000000..137649e29 --- /dev/null +++ b/cloud-claim-check-pattern/call-usage-app/src/test/resources/usageDetailEvent.json @@ -0,0 +1,15 @@ +[ + { + "data": { + "dataFileName": "d8284456-dfff-4bd4-9cef-ea99f70f4835/input.json", + "dataLocation": "callusageapp" + }, + "dataVersion": "v1.0", + "eventTime": "2021-10-25T19:17:15.7468501Z", + "eventType": "UsageDetail", + "id": "d8284456-dfff-4bd4-9cef-ea99f70f4835", + "metadataVersion": "1", + "subject": "UsageDetailPublisher", + "topic": "/subscriptions/0fef643d-a6b1-48f9-a256-ea99f70f4835/resourceGroups/resource-group-ccp/providers/Microsoft.EventGrid/domains/event-grid-domains-ccp/topics/usagecostprocessorfunction-topic" + } +] diff --git a/cloud-claim-check-pattern/etc/Claim-Check-Pattern.png b/cloud-claim-check-pattern/etc/Claim-Check-Pattern.png new file mode 100644 index 0000000000000000000000000000000000000000..a2d8040afaf6c79495f50128bf17a0272cfe7370 GIT binary patch literal 53447 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 literal 0 HcmV?d00001 diff --git a/cloud-claim-check-pattern/etc/claim-check-pattern.urm.puml b/cloud-claim-check-pattern/etc/claim-check-pattern.urm.puml new file mode 100644 index 000000000..14df8b68b --- /dev/null +++ b/cloud-claim-check-pattern/etc/claim-check-pattern.urm.puml @@ -0,0 +1,117 @@ +@startuml +class UsageDetailPublisherFunction [[java:com.iluwatar.producer.calldetails.functions]] { + -messageHandlerUtility: MessageHandlerUtility + -eventHandlerUtility: EventHandlerUtility + +run(): HttpResponseMessage +} + +class UsageCostProcessorFunction [[java:com.iluwatar.consumer.callcostprocessor.functions]] { + -messageHandlerUtilityForUsageDetail: MessageHandlerUtility + -messageHandlerUtilityForUsageCostDetail: MessageHandlerUtility + +run(): HttpResponseMessage +} + +class "MessageHandlerUtility" as MessageHandlerUtility_T [[java:com.iluwatar.claimcheckpattern.utility]] { + +readFromPersistantStorage(messageReference: MessageReference, logger: Logger): Message + +dropToPersistantStorage(message: Message, logger: Logger): void +} + +class "EventHandlerUtility" as EventHandlerUtility_T [[java:com.callusage.utility.PersistentLocalStorageUtility]] { + +publishEvent(customEvent: T, logger: Logger): void +} + +class "Message" as Message_T [[java:com.iluwatar.claimcheckpattern.domain]] { + -messageHeader: MessageHeader + -messageData: MessageData + +Message(messageHeader: MessageHeader, messageData: MessageData) + +getMessageData(): MessageData + +getMessageHeader(): MessageHeader +} + + +class MessageHeader [[java:com.iluwatar.claimcheckpattern.domain]] { + -id: String + -subject: String + -topic: String + -eventType: String + -eventTime: String + -data: Object + -dataVersion: String + +getId(): String + +setId(id: String): void + +getSubject(): String + +setSubject(subject: String): void + +getTopic(): String + +setTopic(topic: String): void + +getEventType(): String + +setEventType(eventType: String): void + +getEventTime(): String + +setEventTime(eventTime: String): void + +getData(): Object + +setData(data: Object): void + +getDataVersion(): String + +setDataVersion(dataVersion:String): void + +} + + +class "MessageBody" as MessageBody_T [[java:com.iluwatar.claimcheckpattern.domain]] { + -data: List[] T + +getData(): List[] T + +setData(data:List[] T): void +} + +class MessageReference [[java:com.iluwatar.claimcheckpattern.domain]] { + -dataLocation: String + -dataFileName: String + +getDataLocation(): String + +setDataLocation(dataLocation:String): void + +getDataFileName(): String + +setDataFileName(dataFileName:String): void +} + +class UsageDetail [[java:com.iluwatar.claimcheckpattern.domain]] { + -userId: String + -duration: int + -data: int + +getUserId(): String + +setUserId(userId: String): void + +getDuration(): long + +setDuration(duration: long): void + +getData(): long + +setData(data: long): void +} + +class UsageCostDetail [[java:com.iluwatar.claimcheckpattern.domain]] { + -userId: String + -callCost: double + -dataCost: double + +getUserId(): String + +setUserId(userId: String): void + +getCallCost(): double + +setCallCost(callCost:double): void + +getDataCost(): double + +setDataCost(dataCost:double) : void +} + + + + + + + +Message_T "1" *-- "1" MessageHeader : has +Message_T "1" *-- "1" MessageBody_T : has +MessageHeader "1" *-- "1" MessageReference : has as data object +MessageBody_T "1" *-- "1" UsageDetail: has +MessageBody_T "1" *-- "1" UsageCostDetail: has + +EventHandlerUtility_T "1" *-- "1" MessageHeader: has +MessageHandlerUtility_T "1" *-- "1" Message_T: has + +UsageDetailPublisherFunction "1" *-- "1" MessageHandlerUtility_T : has +UsageDetailPublisherFunction "1" *-- "1" EventHandlerUtility_T : has + +UsageCostProcessorFunction "1" *-- "1" MessageHandlerUtility_T : has +UsageCostProcessorFunction "1" *-- "1" MessageHandlerUtility_T : has +@enduml \ No newline at end of file diff --git a/cloud-claim-check-pattern/etc/class-diagram.png b/cloud-claim-check-pattern/etc/class-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..d627b1b70c21f4fad1079a0c01ebe385965da2b4 GIT binary patch literal 110789 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 literal 0 HcmV?d00001 diff --git a/cloud-claim-check-pattern/pom.xml b/cloud-claim-check-pattern/pom.xml new file mode 100644 index 000000000..3f41053c0 --- /dev/null +++ b/cloud-claim-check-pattern/pom.xml @@ -0,0 +1,69 @@ + + + + + + com.iluwatar + java-design-patterns + 1.25.0-SNAPSHOT + + + 4.0.0 + claim-check-pattern + pom + + + call-usage-app + + + + com.google.code.gson + gson + 2.8.8 + + + org.junit.jupiter + junit-jupiter + 5.8.1 + test + + + org.mockito + mockito-junit-jupiter + 4.0.0 + test + + + + org.mockito + mockito-inline + 4.0.0 + test + + + + \ No newline at end of file