{"id":36416952,"url":"https://github.com/adobe/bridgeservice","last_synced_at":"2026-01-11T17:00:02.559Z","repository":{"id":318402786,"uuid":"1066992437","full_name":"adobe/bridgeService","owner":"adobe","description":"The BridgeService is a library that allows your project to access java code to which you do not have implicite and normal access. Use cases are JS/Python/C++ accessing Java objects or java objects that are protected, and that you do not want to distribute as a library. ","archived":false,"fork":false,"pushed_at":"2025-12-23T07:44:03.000Z","size":177,"stargazers_count":1,"open_issues_count":11,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-24T22:14:01.079Z","etag":null,"topics":["cross-compiler","cross-platform","integro","jni","jni-java","omg"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adobe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-30T08:32:13.000Z","updated_at":"2025-10-01T19:14:42.000Z","dependencies_parsed_at":"2025-10-07T02:28:50.978Z","dependency_job_id":"b3e92223-eac8-43d1-b532-33e6a984afa4","html_url":"https://github.com/adobe/bridgeService","commit_stats":null,"previous_names":["adobe/bridgeservice"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/adobe/bridgeService","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2FbridgeService","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2FbridgeService/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2FbridgeService/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2FbridgeService/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adobe","download_url":"https://codeload.github.com/adobe/bridgeService/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2FbridgeService/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28314253,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T14:58:17.114Z","status":"ssl_error","status_checked_at":"2026-01-11T14:55:53.580Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cross-compiler","cross-platform","integro","jni","jni-java","omg"],"created_at":"2026-01-11T17:00:01.579Z","updated_at":"2026-01-11T17:00:02.550Z","avatar_url":"https://github.com/adobe.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BridgeService\n\n[![unit-tests](https://github.com/adobe/bridgeService/actions/workflows/onPushSimpleTest.yml/badge.svg)](https://github.com/adobe/bridgeService/actions/workflows/onPushSimpleTest.yml)\n[![codecov](https://codecov.io/gh/adobe/bridgeService/branch/main/graph/badge.svg?token=GSi0gUlqq5)](https://codecov.io/gh/adobe/bridgeService)\n[![javadoc](https://javadoc.io/badge2/com.adobe.campaign.tests.bridge.service/integroBridgeService/javadoc.svg)](https://javadoc.io/doc/com.adobe.campaign.tests.bridge.service/integroBridgeService)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=adobe_bridgeService\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=adobe_bridgeService)\n\nThe BridgeService allows you to expose your Java project/library as a REST service. It allows you to make calls to Java code\nfrom any language or framework you are in.\n\n## Table of Contents\n\n\u003c!-- TOC --\u003e\n* [BridgeService](#bridgeservice)\n  * [Table of Contents](#table-of-contents)\n  * [Background](#background)\n    * [Demo Project](#demo-project)\n  * [Release Notes](#release-notes)\n  * [Implementing The Bridge Service in Your Project](#implementing-the-bridge-service-in-your-project)\n    * [Adding the Bridge Service to Your Project](#adding-the-bridge-service-to-your-project)\n        * [Installation](#installation)\n      * [Considerations](#considerations)\n    * [Including your project in the BridgeService](#including-your-project-in-the-bridgeservice)\n  * [Starting the Bridge Service](#starting-the-bridge-service)\n    * [Running the Bridge Locally](#running-the-bridge-locally)\n    * [Running a DEMO](#running-a-demo)\n  * [Setting Information About your Environment](#setting-information-about-your-environment)\n  * [Testing That all is Working](#testing-that-all-is-working)\n  * [Testing That all External Devices can be Accessed](#testing-that-all-external-devices-can-be-accessed)\n  * [Making Java Calls](#making-java-calls)\n    * [A basic Java Call](#a-basic-java-call)\n    * [Instantiating Objects](#instantiating-objects)\n    * [Call Chaining a basic Java Call](#call-chaining-a-basic-java-call)\n    * [Call Chaining and Call Dependencies](#call-chaining-and-call-dependencies)\n      * [Call Chaining and Instance Methods](#call-chaining-and-instance-methods)\n    * [Argument Types](#argument-types)\n      * [Simple Java Objects](#simple-java-objects)\n      * [Lists and Arrays](#lists-and-arrays)\n      * [Complex Types](#complex-types)\n      * [Files](#files)\n  * [Results](#results)\n    * [Formatting Dates](#formatting-dates)\n    * [Deserialization Plugins](#deserialization-plugins)\n  * [Managing Timeouts](#managing-timeouts)\n    * [Setting Timeout Globally](#setting-timeout-globally)\n    * [Setting a Timeout for the Call Session](#setting-a-timeout-for-the-call-session)\n  * [Creating a Call Context](#creating-a-call-context)\n    * [Static Variable Scopes](#static-variable-scopes)\n      * [Session Scopes](#session-scopes)\n      * [Product Scope](#product-scope)\n  * [Headers and Secrets](#headers-and-secrets)\n    * [Secrets](#secrets)\n    * [Steamlining Headers](#steamlining-headers)\n  * [Making Assertions](#making-assertions)\n    * [Duration-Based Assertions](#duration-based-assertions)\n  * [Error Management](#error-management)\n  * [Contributing to the Project](#contributing-to-the-project)\n  * [Known Errors](#known-errors)\n    * [Linked Error](#linked-error)\n  * [Known Issues and Limitations](#known-issues-and-limitations)\n    * [Cannot call overloaded methods with the same number of arguments.](#cannot-call-overloaded-methods-with-the-same-number-of-arguments)\n    * [Only simple arguments](#only-simple-arguments)\n    * [Complex Non-Serializable Return Objects](#complex-non-serializable-return-objects)\n    * [Calling Enum Methods](#calling-enum-methods)\n\u003c!-- TOC --\u003e\n\n## Background\nWe originally created this project to address the need for Cypress tests to reuse code created for the back-end tests. We had a lot of product knowledge and tooling stored in the back-end tests, that rewriting them in node would not have been practical. Today the project is up and running and is used regularly in our test projects. \n\n### Demo Project\nWe have created a demo project that shpws how the bridge service can be implemented. It is available under [Test As A Product Demo](https://github.com/adobe/test-as-a-product-demo).\n\n## Release Notes\n\nThe release notes can be found [here](ReleaseNotes.md).\n\n## Implementing The Bridge Service in Your Project\n\nThe bridge service can be used in two ways:\n\n* By adding it to the project you want to expose (recommended),\n* By including your project as a dependency to the Bridge cervice deployed.\n\n### Adding the Bridge Service to Your Project\n\nWe think it is simplest to the BridgeService dependency to your project. This allows you to only update your code when\nneeded, and you do not need to create a new release/snapshot everytime your project changes.\n\n![BridgeService Injection Model](diagrams/Processes-injectionModel.drawio.png)\n\nWhen starting the bridge service you need to run the following command line:\n\n```\nmvn compile exec:java -Dexec.mainClass=MainContainer -Dexec.args=\"test\"\n```\n\n##### Installation\n\nThe following dependency needs to be added to your pom file:\n\n```\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.adobe.campaign.tests.bridge.service\u003c/groupId\u003e\n    \u003cartifactId\u003eintegroBridgeService\u003c/artifactId\u003e\n    \u003cversion\u003e2.11.18\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n#### Considerations\n\nSince the BridgeService uses Jetty and java Spark, it is quite possible that there maybe conflicts in the project when\nyou add this library. Most importantly you will need to ensure that `javax.servlet` is set to \"**compile**\" in your\nmaven scope.\n\nWe have found it simplest to simply add that library directly in the pom file with the scope \"**compile**\".\n\n### Including your project in the BridgeService\n\nIn this model you can simply add your project as a dependency to the BridgeProject.\n\n![BridgeService Aggregator Model](diagrams/Processes-aggregatorModel.drawio.png)\n\n## Starting the Bridge Service\n\nWhen deploying this as a project we run this as an executable jar. This is usually done in a Docker image.\n\n### Running the Bridge Locally\n\nYou can also run the project locally to debug your project. To do this, you need to run the following command line:\n\nfrom the root project:\n```mvn -pl integroBridgeService exec:java -Dexec.args=\"test\"```\n\nor directly from the module \"integroBridgeService\":\n```mvn exec:java -Dexec.args=\"test\"```\n\nThis will make the service available under :\n```http://localhost:8080```\n\n### Running a DEMO\n\nThe bridge service can be launched in this project with a demo project (Included in an aggregator mode). When deployed\nin this mode, we include the module `bridgeService-data` which is part of this project. If you want to include this\nproject in your deployment you need to set the property `demo.project.mode` to `compile`.\n\nfrom the root project:\n```mvn -pl integroBridgeService exec:java -Dexec.args=\"test\" -Ddemo.project.mode=compile ```\n\nor directly from the module \"integroBridgeService\":\n```mvn exec:java -Dexec.args=\"test\" -Ddemo.project.mode=compile```\n\n## Setting Information About your Environment\n\nThe users accessing bridge service will encounter two different technologies:\n\n* The Bridge Service\n* The Host Project\n\nIn order to make provide context information the Bridge Service will always let you know which version it is. However,\nwe need to let the users know about the version of the host project. Ths version number can be set by setting the\nenvironment property `IBS.PRODUCT.USER.VERSION`.\n\n## Testing That all is Working\n\nAll you need to do is to call :\n```/test```\n\nIf all is good you should get:\n\n```\nAll systems up - in production\nVersion : 2.11.16\nProduct user version : 7.0\n```\n\nNote: _The 'Product user version' is a value that you set in the environment variables, and is intended for the\nconsumers._\n\n## Testing That all External Devices can be Accessed\n\nOne of the added values of this service is to create a single point of access for external dependencies. However, this\nneeds to be checked, before using this service. In order to do this you need to the following POST call:\n\n```\n/service-check\n```\n\nThe payload needs to have the following format:\n\n```JSON\n{\n  \"\u003cURL ID 1\u003e\": \"\u003cdns 1\u003e:\u003cPort\u003e\",\n  \"\u003cURL ID 2\u003e\": \"\u003cdns 2\u003e:\u003cPort\u003e\"\n}\n```\n\nThe payload returns a JSON with the test results:\n\n```JSON\n{\n  \"\u003cURL ID 1\u003e\": true,\n  \"\u003cURL ID 2\u003e\": false\n}\n```\n\nIn the example above \"\u003cURL ID 2\u003e\" is marked as false because it can not be accessed from the BridgeService.\n\n## Making Java Calls\n\n### A basic Java Call\n\nThe simplest java call is done in the following way:\n```/call```\n\n```JSON\n{\n  \"callContent\": {\n    \"\u003cID\u003e\": {\n      \"class\": \"\u003cpackage name\u003e.\u003cclass Name\u003e\",\n      \"method\": \"\u003cmethod name\u003e\",\n      \"args\": [\n        \"argument1\",\n        \"argument2\"\n      ]\n    }\n  }\n}\n```\n\nIf the IntegroBridgeService can find the method it will execute it. The result is, when successful, is encapsulated in\na 'returnValues' object.\n\n```JSON\n{\n  \"returnValues\": {\n    \"\u003cID\u003e\": \"\u003cresult\u003e\"\n  },\n  \"callDurations\": {\n    \"\u003cID\u003e\": \"\u003cduration ms\u003e\"\n  }\n}\n```\n\nHere is an example for the POST call `http://localhost:8080/call` and the payload:\n\n```JSON\n{\n  \"callContent\": {\n    \"fetchString1\": {\n      \"class\": \"com.adobe.campaign.tests.bridge.testdata.one.SimpleStaticMethods\",\n      \"method\": \"methodAcceptingStringArgument\",\n      \"args\": [\n        \"REAL\"\n      ]\n    }\n  }\n}\n```\n\n`SimpleStaticMethods.methodAcceptingStringArgument` accepts a string argument and concatenates the given argument\nwith `_SUCCESS`. The call will return the following result:\n\n```JSON\n{\n  \"callDurations\": {\n    \"fetchString1\": 7\n  },\n  \"returnValues\": {\n    \"fetchString1\": \"REAL_Success\"\n  }\n}\n```\n\n### Instantiating Objects\n\nIf we do not specify a method, the bridge service assumes that we are instantiating the given class:\n\n```JSON\n{\n  \"callContent\": {\n    \"\u003cID\u003e\": {\n      \"class\": \"\u003cpackage name\u003e.\u003cclass Name\u003e\",\n      \"args\": [\n        \"argument1\",\n        \"argument2\"\n      ]\n    }\n  }\n}\n```\n\n**Note :** You can also set the method name to the class name, but it may be easier to simply skip setting a method name\nin this case.\n\n### Call Chaining a basic Java Call\n\nWe can chain a series of java calls in the same payload:\n\n```JSON\n{\n  \"callContent\": {\n    \"\u003cID-1\u003e\": {\n      \"class\": \"\u003cpackage name 1\u003e.\u003cclass name 1\u003e\",\n      \"method\": \"\u003cmethod name 1\u003e\",\n      \"args\": [\n        \"argument1\",\n        \"argument2\"\n      ]\n    },\n    \"\u003cID-2\u003e\": {\n      \"class\": \"\u003cpackage name 2\u003e.\u003cclass name 2\u003e\",\n      \"method\": \"\u003cmethod name 2\u003e\",\n      \"args\": [\n        \"argument1\",\n        \"argument2\"\n      ]\n    }\n  }\n}\n```\n\nIn the example above the results will be stored in the following way:\n\n```JSON\n{\n  \"returnValues\": {\n    \"\u003cID-1\u003e\": \"\u003cresult\u003e\",\n    \"\u003cID-2\u003e\": \"\u003cresult\u003e\"\n  },\n  \"callDurations\": {\n    \"\u003cID-1\u003e\": \"\u003cduration ms\u003e\",\n    \"\u003cID-2\u003e\": \"\u003cduration ms\u003e\"\n  }\n}\n```\n\n### Call Chaining and Call Dependencies\n\nWe now have the possibility of injecting call results from one call to the other:\n\n```JSON\n{\n  \"callContent\": {\n    \"\u003cID-1\u003e\": {\n      \"class\": \"\u003cpackage name 1\u003e.\u003cclass name 1\u003e\",\n      \"method\": \"\u003cmethod name 1\u003e\",\n      \"args\": [\n        \"argument1\",\n        \"argument2\"\n      ]\n    },\n    \"\u003cID-2\u003e\": {\n      \"class\": \"\u003cpackage name 2\u003e.\u003cclass name 2\u003e\",\n      \"method\": \"\u003cmethod name 2\u003e\",\n      \"args\": [\n        \"\u003cID-1\u003e\",\n        \"argument2\"\n      ]\n    }\n  }\n}\n```\n\nIn the example above \"ID-2\" will use the return value of the call \"ID-1\" as ts first argument.\n\n**NOTE** : When passing a call result as an argument, it needs to be a String. In many languages such as JavaScript, the\nJSON keys need not be a string, however, for this to work you need to pass the ID as a string.\n\nHere is an example of for a call chaining:\n\n```JSON\n{\n  \"callContent\": {\n    \"fetchStringsList\": {\n      \"class\": \"com.adobe.campaign.tests.bridge.testdata.one.SimpleStaticMethods\",\n      \"method\": \"methodReturningList\",\n      \"args\": []\n    },\n    \"fetchSubjects\": {\n      \"class\": \"com.adobe.campaign.tests.bridge.testdata.one.SimpleStaticMethods\",\n      \"method\": \"methodAcceptingListArguments\",\n      \"args\": [\n        \"fetchStringsList\"\n      ]\n    }\n  }\n}\n```\n\n`methodReturningList` returns a list of Strings. `methodAcceptingListArguments` accepts a list and returns its size. As\nyou can see we have passed the identity of the first call, `fetchStringsList` to the second one `fetchSubjects`. Here\nis the return payload:\n\n```JSON\n{\n  \"callDurations\": {\n    \"fetchStringsList\": 5,\n    \"fetchSubjects\": 1\n  },\n  \"returnValues\": {\n    \"fetchStringsList\": [\n      \"NA1\",\n      \"NA2\",\n      \"NA3\",\n      \"NA4\"\n    ],\n    \"fetchSubjects\": 4\n  }\n}\n```\n\n#### Call Chaining and Instance Methods\n\nWe now have the possibility of injecting call results from one call to the other. In the example below we instantiate an\nobject, and in the following call we call a method of that object. This is done by passing the ID of the first call as\nthe `instance` value for the following call.\n\n```JSON\n{\n  \"callContent\": {\n    \"\u003cID-1\u003e\": {\n      \"class\": \"\u003cpackage name\u003e.\u003cclass name\u003e\",\n      \"args\": [\n        \"argument1\",\n        \"argument2\"\n      ]\n    },\n    \"\u003cID-2\u003e\": {\n      \"class\": \"\u003cID-1\u003e\",\n      \"method\": \"\u003cmethod name\u003e\",\n      \"args\": [\n        \"argument2\"\n      ]\n    }\n  }\n}\n```\n\nIn the example above \"ID-2\" will use call the instance method of the object created in call \"ID-1\".\n\n### Argument Types\n\nSince we are using JSON to pass values to the method, we need to cover how different types are passed.\n\n#### Simple Java Objects\n\nThe internal Java objects such as int, String and boolean can be passed with no problems\n\n#### Lists and Arrays\n\nList and Arrays can be passed as JSONArrays. IBS will transform them to the target argument when needed (_Available\nsince 2.116_).\n\n#### Complex Types\n\nSome methods require complex Objects as arguments. In this case you need to have a constructor/factory call in one call,\nand pass they key as an argument.\n\n#### Files\n\nAs of version 2.11.16 we have the possibility to pass a file to the bridgeService. When doing so, you need to send your\nrequest as a multi-part request. As in most multi-part requests, you need to give each uploaded file a key value. In\nthat case the file is referenced with that key value.\n\nBelow is an example using curl (_executed from the project root_). We are uploading the file `integroBridgeService/src/test/resources/uploadFiles/testaRosa.txt` with the id `uploaded_file`, like in call chaining we have passed this id to the method call `fileReader`, whose job is to return the file contents.\n\n```shell\ncurl --request POST \\\n  --url http://localhost:8080/call \\\n  --header 'Content-Type: multipart/form-data' \\\n  --form 'jsonbody={\n        \"assertions\": {},\n        \"timeout\": 10000,\n        \"callContent\": {\n                \"fileReader\": {\n                        \"class\": \"com.adobe.campaign.tests.bridge.testdata.one.SimpleStaticMethods\",\n                        \"method\": \"methodAcceptingFile\",\n                        \"args\": [\n                                \"uploaded_file\"\n                        ]\n\n                }\n        },\n        \"environmentVariables\": {}\n}' \\\n  --form uploaded_file=@integroBridgeService/src/test/resources/uploadFiles/testaRosa.txt\n\n```\n\nThe result is then:\n\n```JSON\n{\n  \"callDurations\": {\n    \"call1PL\": 7\n  },\n  \"returnValues\": {\n    \"fileReader\": \"Hello World\"\n  }\n}\n```\n\n## Results\nResults are returned as a JSON Object. Serializable return objects are deserialized. For objects that are not Serializable, we perform an operatio called scraping, which involves sequentially calling the simple getters of the object, and include the results in the result object.\n\nIn the case of complex classes where the scraping is not sufficient, you can define a deserialization plugin for that class. This allow you to be specific regarding how the object can be returned. For mor information on this you can refer to the chapter [Deserialization Plugins](#deserialization-plugins).\n\n### Formatting Dates\nWe now allow the extraction and the formatting of Dates. This is done by setting the environment variable `IBS.DESERIALIZATION.DATE.FORMAT`. If not set the date is not changed and remains a long. The format we cover is [SimpleDateFormat](https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html). A wrong Date format will result in using the default format (long).\n\n### Deserialization Plugins\nAs of version 2.11.17, we introduced the notion of plugins. For now you can customize how an object is deserialized. This can be usefull when the default object serialization is incomplete or not to your liking.\n\nTo create your own plugin you need to:\n* Implement the interface methods of the interface `com.adobe.campaign.tests.bridge.service.plugins.IBSDeserializerPlugin`.\n* Flag the package of the plugin in the environment variable `IBS.PLUGINS.PACKAGE`.\n\nThere is an example of the plugin in the tests under `integroBridgeService/src/test/java/com/adobe/campaign/tests/bridge/plugins/deserializer/MimeExtractionPluginDeserializer.java`.\n\n## Managing Timeouts\n\nAs of version 2.11.6 we now introduce the notion of timeouts. This means that after a declared time a call will be\ninterrupted. Setting this value can be done at two levels:\n\n* The deployment level\n* The Call session\n\n**Note :** If set to 0, there is no timeout.\n\n### Setting Timeout Globally\n\nYou can set a default value when starting the service. This is done by setting the environment\nvariable `IBS.TIMEOUT.DEFAULT`. If not set, the default value is 10000ms.\n\n### Setting a Timeout for the Call Session\n\nWe can also set the Timeout for a java call transaction. In that case the value you pass overrides the global value, but\nonly for you session. If the `timeout` is not test in the payload at the next call, the global value will be used.\n\nIn the example below the method `methodWithTimeOut` waits for the provided, in this case 800ms, amount of time. In the\nexample below the test will pass because we wait for 800ms, and the timeout is 1000s.\n\n```JSON\n{\n  \"callContent\": {\n    \"call1\": {\n      \"class\": \"com.adobe.campaign.tests.bridge.testdata.one.SimpleStaticMethods\",\n      \"method\": \"methodWithTimeOut\",\n      \"args\": [\n        800\n      ]\n    }\n  },\n  \"timeout\": 1000\n}\n```\n\nIf the payload above would have a timeout below 800ms, the call will fail.\n\n## Creating a Call Context\n\nWe sometimes need to set environment variables when making calls. This is usually indirectly related to the call you are\ndoing. These variable mirror the values of a property file, so they are always treated as strings.\n\n```JSON\n{\n  \"callContent\": {\n    \"\u003cID\u003e\": {\n      \"class\": \"\u003cpackage name\u003e.\u003cclass Name\u003e\",\n      \"method\": \"\u003cmethod name\u003e\",\n      \"args\": [\n        \"argument1\",\n        \"argument2\"\n      ]\n    }\n  },\n  \"environmentVariables\": {\n    \"\u003cENVIRONMENT PROPERTY 1\u003e\": \"\u003cvalue\u003e\"\n  }\n}\n```\n\nWhen making the call we first update the environment variables for the system.\n\nThis call will use your internal method for setting environment variables. This method can be set by setting the\nfollowing environment values, when activating the Bridge on your project:\n\n* IBS.ENVVARS.SETTER.CLASS\n* IBS.ENVVARS.SETTER.METHOD\n\n### Static Variable Scopes\n\nOne of our main concerns has been the management of static variables. For the sake of conversation we need to identify\nscopes:\n\n* **Session Scope** : Access to the variables in the same call to the Bridge Service\n* **Product Scope** : Access to the variables between two different calls\n\n#### Session Scopes\n\nFor now our approach is that two distinct calls to the same Bridge Service node, should share little or no variables.\nAnother way of defining this is that two calls should not interfere with one another. In a Session Context we have two\nuse cases:\n\nWe have covered all the use cases in the\ndocument [Managing Contexts and Static Variables](./docs/Technical.md#managing-contexts-and-static-variables).\n\n#### Product Scope\n\nAlthough we do not, yet, provide tools for managing variables that are valid for all calls to the IBS, we can define a\nseries or local environment variables are deployment of the service. This can be done in two ways:\n\n* Managing a properties for in your deployment\n* Injecting Runtime properties at the commandline\n\n## Headers and Secrets\n\nAs of version 2.11.16, we can now use header variables in the payload. This feature was developed for two reasons:\n\n* Avoiding the passing o secrets directly in the JSON payload.\n* Allowing for users to re-use the same JSON payload for different values.\n\nAll you need to do is to reference your header name in the `args` section.\n\nExample:\n\n```shell\ncurl --request POST \\\n  --url http://localhost:8080/call \\\n  --header 'Content-Type: application/json' \\\n  --header 'ibs-header-var1: MyValue' \\\n  --data '{\n\t\"callContent\": {\n\t\t\"fetchHeader\": {\n\t\t\t\"class\": \"com.adobe.campaign.tests.bridge.testdata.one.SimpleStaticMethods\",\n\t\t\t\"method\": \"methodAcceptingStringArgument\",\n\t\t\t\"args\": [\n\t\t\t\t\"ibs-header-var1\"\n\t\t\t]\n\t\t}\n\t}\n}'\n```\n\nIn the call above we pass `MyValue` with the key `ibs-header-var1` as a header. Our payload will fetch the value in\nthe `args`section. The call will return :\n\n```JSON\n{\n  \"callDurations\": {\n    \"fetchString1\": 12\n  },\n  \"returnValues\": {\n    \"fetchString1\": \"MyValue_Success\"\n  }\n}\n```\n\n### Secrets\n\nSecrets allow you to have an extra level of security. This will mean that we will not allow you to print the secret in\nthe output.\n\nA secret sent to the IBS will have to be prefixed with `ibs-secret-`. This can be overridden by setting the run-time\nvariable `IBS.SECRETS.FILTER.PREFIX`.\n\nIn the example earlier, if `MyValue` were to be passed as a secret (with a prefix `ibs-secret-`), we would be getting an\nexception:\n\n```shell\ncurl --request POST \\\n  --url http://localhost:8080/call \\\n  --header 'Content-Type: application/json' \\\n  --header 'ibs-header-var1: MyValue' \\\n  --data '{\n\t\"callContent\": {\n\t\t\"fetchHeader\": {\n\t\t\t\"class\": \"com.adobe.campaign.tests.bridge.testdata.one.SimpleStaticMethods\",\n\t\t\t\"method\": \"methodAcceptingStringArgument\",\n\t\t\t\"args\": [\n\t\t\t\t\"ibs-secret-var1\"\n\t\t\t]\n\t\t}\n\t}\n}'\n```\nBelow is the exception we will get: \n\n```JSON\n{\n  \"title\": \"We detected an inconsistency in your payload.\",\n  \"code\": 404,\n  \"detail\": \"Your return payload contains secrets. You may consider re-evaluating the headers you send. If they are not a secret, they can be put directly in the payload. Otherwise you can simply disable the IBS.HEADERS.BLOCK.OUTPUT option.\",\n  \"bridgeServiceException\": \"com.adobe.campaign.tests.bridge.service.exceptions.IBSPayloadException\"\n}\n```\n\nSometimes you may want to debug the system. In these cases you can deactivate the output check by setting run-time\nvariable `IBS.SECRETS.BLOCK.OUTPUT` to false. However, this should only be temporary, and in production it is best to\nkeep this control.\n\n### Steamlining Headers\n\nBy default, IBS stores all the headers when you send a call. You have the possibility to filter the headers you want to\nuse by setting the run-time variable `IBS.HEADERS.FILTER.PREFIX`.\n\n## Making Assertions\n\nAs of version 2.11.16, we allow the user to define assertions. An assertion allows users to define acceptance criteria\nfor a call. They can also allow users to delegate the execution to a third party, by defining what an acceptable outcome\nfor a result should be. This has been implemented by\nembedding [Hamcrest Matchers](https://hamcrest.org/JavaHamcrest/javadoc/2.2/org/hamcrest/Matchers.html) in the bridge\nservice. You can now define a matcher to define rules for the correctness of a call.\n\nAssertions in IBS will allow you to reference different calls you have previously made in the \"callContent\" section.\nJust as in argument epansion, we will fetch the result of the call and use in the assertion.\n\nAn assertion, in its most basic form, can be done in the following way:\n\n```JSON\n{\n  \"callContent\": {\n    \"\u003cID\u003e\": {\n      \"class\": \"\u003cpackage name\u003e.\u003cclass Name\u003e\",\n      \"method\": \"\u003cmethod name\u003e\",\n      \"args\": [\n        \"argument1\",\n        \"argument2\"\n      ]\n    }\n  },\n  \"assertions\": {\n    \"\u003cAssertion Title\u003e\": {\n      \"matcher\": \"\u003cA matcher defined in the org.hamcrest.Matchers class\u003e\",\n      \"actualValue\": \"\u003cID\u003e as referenced in the call value. or a simple value\",\n      \"expectedValue\": \"A value or an ID\"\n    }\n  }\n}\n```\n\nThe assertions will then be present in the return payload:\n\n```JSON\n{\n  \"returnValues\": {\n    \"\u003cID\u003e\": \"\u003cresult\u003e\"\n  },\n  \"callDurations\": {\n    \"\u003cID\u003e\": \"\u003cduration ms\u003e\"\n  },\n  \"assetions\": {\n    \"\u003cAssertion Title\u003e\": \"\u003ctrue or false\u003e\"\n  }\n}\n```\n\nexample:\n\n```JSON\n{\n  \"callContent\": {\n    \"fetchString1\": {\n      \"class\": \"com.adobe.campaign.tests.bridge.testdata.one.SimpleStaticMethods\",\n      \"method\": \"methodReturningString\"\n    },\n    \"fetchString2\": {\n      \"class\": \"com.adobe.campaign.tests.bridge.testdata.one.SimpleStaticMethods\",\n      \"method\": \"methodReturningString\"\n    }\n  },\n  \"assertions\": {\n    \"Both values should be the same\": {\n      \"matcher\": \"equalTo\",\n      \"actualValue\": \"fetchString1\",\n      \"expectedValue\": \"fetchString2\"\n    }\n  }\n}\n```\n\nBy default, assertions in the Bridge Service will look at the resulut of a call, however, you can chose a different\nbehavior or this. Currently, assertions are of two types:\n\n* Result Based,\n* Duration Based\n\n### Duration-Based Assertions\n\nAs mentioned earlier an assertion can be duration based. In that case, IBS will consider the call duration of a call for\nthe assertion. In order to perform an assertion the payload needs to include the entry `\"type\": \"DURATION\"` to the\npayload:\n\n```JSON\n{\n  \"callContent\": {\n    \"\u003cID\u003e\": {\n      \"class\": \"\u003cpackage name\u003e.\u003cclass Name\u003e\",\n      \"method\": \"\u003cmethod name\u003e\",\n      \"args\": [\n        \"argument1\",\n        \"argument2\"\n      ]\n    }\n  },\n  \"assertions\": {\n    \"\u003cAssertion Title\u003e\": {\n      \"type\": \"DURATION\",\n      \"matcher\": \"\u003cA matcher defined in the org.hamcrest.Matchers class\u003e\",\n      \"actualValue\": \"\u003cID\u003e\",\n      \"expectedValue\": \"Expected duration for ID in milli-seconds\"\n    }\n  }\n}\n```\n\nWhen set, the assertion will use the call duration of the call, and use it in the assertion evaluation.\n\nExample:\n\n```JSON\n{\n  \"callContent\": {\n    \"spendTime\": {\n      \"class\": \"com.adobe.campaign.tests.bridge.testdata.one.SimpleStaticMethods\",\n      \"method\": \"methodWithTimeOut\",\n      \"args\": [\n        100\n      ]\n    }\n  },\n  \"assertions\": {\n    \"The duration should not be greater than 100\": {\n      \"type\": \"DURATION\",\n      \"matcher\": \"greaterThanOrEqualTo\",\n      \"actualValue\": \"spendTime\",\n      \"expectedValue\": \"100\"\n    }\n  }\n}\n```\n\n## Error Management\n\nCurrently, whenever there is an error in the underlying java call we will include the orginal error message in the error\nresponse. For example, for the call:\n\n```json\n{\n  \"callContent\": {\n    \"call1\": {\n      \"class\": \"com.adobe.campaign.tests.bridge.testdata.one.SimpleStaticMethods\",\n      \"method\": \"methodThrowingException\",\n      \"returnType\": \"java.lang.String\",\n      \"args\": [\n        3,\n        3\n      ]\n    }\n  }\n}\n```\n\nWe would normally get the error:\n\n```\njava.lang.IllegalArgumentException: We do not allow numbers that are equal.\n```\n\nWhen using the bridge service, we also include additional info:\n\n```JSON\n{\n  \"title\": \"A title describing the exception\",\n  \"code\": 500,\n  \"detail\": \"A detailed description of the problem\",\n  \"bridgeServiceException\": \"com.adobe.campaign.tests.bridge.service.exceptions.TargetJavaMethodCallException\",\n  \"originalException\": \"java.lang.IllegalArgumentException\",\n  \"originalMessage\": \"The message of the originating exception\",\n  \"failureAtStep\": \"Step name\",\n  \"stackTrace\": [\n    \"ClassA.methodA\",\n    \"ClassB.methodB\"\n  ]\n}\n```\n\nThe BridgeService exception is how the bridgeService manages underlying errors. However, we also share the:\n\n* The title of the failure\n* The error code\n* The bridgeService error category\n* The Originating exception\n* The Originating exception message\n* The step at which the error occured\n* The stack trace of the originating exception\n\n## Contributing to the Project\n\nThere are two main docs for contributing:\n\n* [The Contributing Doc](CONTRIBUTING.md) For general contribution rules.\n* [The Technical Doc](docs/Technical.md) For general technical aspects.\n\n## Known Errors\n\n### Linked Error\n\nWhen using the \"manual\" mode, this error can happen when you are chaining calls, and that the called classes call a\nthird class in a static way. In such cases you will get an error like:\n\n```\nProblems with payload. Check the passed environment variables.\njava.lang.LinkageError: loader  constraint violation: when resolving method \"com.adobe.campaign.tests.bridge.testdata.issue34.pckg2.MiddleManClassFactory.getMarketingInstance()Lcom/adobe/campaign/tests/bridge/testdata/issue34/pckg1/MiddleMan;\" the class loader com.adobe.campaign.tests.bridge.service.IntegroBridgeClassLoader @697a1a68 (instance of com.adobe.campaign.tests.bridge.service.IntegroBridgeClassLoader, child of 'app' jdk.internal.loader.ClassLoaders$AppClassLoader) of the current class, com/adobe/campaign/tests/bridge/testdata/issue34/pckg1/CalledClass2, and the class loader 'app' (instance of jdk.internal.loader.ClassLoaders$AppClassLoader) for the method's defining class, com/adobe/campaign/tests/bridge/testdata/issue34/pckg2/MiddleManClassFactory, have different Class objects for the type com/adobe/campaign/tests/bridge/testdata/issue34/pckg1/MiddleMan used in the signature\n```\n\nThis usually means that some additional packages need to be included in the environment\nvariable: `IBS.CLASSLOADER.STATIC.INTEGRITY.PACKAGES`.\n\n## Known Issues and Limitations\n\nAs this is a new project there are a few limitations to our solution:\n\n### Cannot call overloaded methods with the same number of arguments.\n\nToday, in order to simply the call model, we have chosen not to specify the argument types in the call. The consequence\nof this is that in the case of overloaded methods, we only pick the method with the same number of arguments. If two\nsuch overloaded methods exist, we choose to throw an exception:\n``We could not find a unique method for \u003cmethod\u003e.``\n\n### Only simple arguments\n\nSince this is a REST call we can only correctly manage simple arguments in the payload. One workaround is to use Call\nDependencies in Call Chaining (see above). I.e. you can pass simple arguments to one method, and use the complex results\nof that method as an argument for the following java call.\n\n### Complex Non-Serializable Return Objects\n\nIn many cases the object a method returns is not serializable. If that is the case we mine the object, and extract all\nsimple values from the object.\n\nThe mining or \"scraping\" is done by calling all the visible getters of the object. This can be nested, with a limit of three levels. You can modify this by setting the environment variable `IBS.DESERIALIZATION.DEPTH.LIMIT`.\n\n### Calling Enum Methods\n\nWe are currently unable to call enums with the Bridge Service.\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadobe%2Fbridgeservice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadobe%2Fbridgeservice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadobe%2Fbridgeservice/lists"}