├── .gitignore ├── .reuse └── dep5 ├── CREDITS.txt ├── LICENSE ├── LICENSES └── Apache-2.0.txt ├── README.adoc ├── emjapi-samples-jms-p2p ├── README.adoc ├── config │ ├── em-config-default.json │ └── em-config-dev.json ├── manifest.yml ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── sap │ │ └── xbem │ │ └── sample │ │ └── sapcp │ │ └── jms │ │ └── p2p │ │ ├── Application.java │ │ ├── config │ │ ├── MessagingServiceConfig.java │ │ └── TokenRequest.java │ │ └── services │ │ └── MessagingServiceRestController.java │ └── resources │ └── static │ └── index.html ├── emjapi-samples-jms-pubsub ├── README.adoc ├── config │ ├── em-config-default.json │ └── em-config-dev.json ├── manifest.yml ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── sap │ │ └── xbem │ │ └── sample │ │ └── sapcp │ │ └── jms │ │ └── p2p │ │ ├── Application.java │ │ ├── config │ │ └── MessagingServiceConfig.java │ │ └── services │ │ └── MessagingServiceRestController.java │ └── resources │ └── static │ └── index.html └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Initial created by .ignore support plugin (hsz.mobi) 2 | ### 3 | # project specfific excludes 4 | incubator 5 | 6 | ### Java template 7 | *.class 8 | 9 | *.iml 10 | .idea 11 | 12 | # Package Files # 13 | *.jar 14 | *.war 15 | *.ear 16 | 17 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 18 | hs_err_pid* 19 | ### Maven template 20 | target/ 21 | pom.xml.tag 22 | pom.xml.releaseBackup 23 | pom.xml.versionsBackup 24 | pom.xml.next 25 | release.properties 26 | dependency-reduced-pom.xml 27 | buildNumber.properties 28 | .mvn/timing.properties 29 | 30 | # Exclude maven wrapper 31 | !/.mvn/wrapper/maven-wrapper.jar 32 | ### macOS template 33 | *.DS_Store 34 | .AppleDouble 35 | .LSOverride 36 | 37 | # Icon must end with two \r 38 | Icon 39 | 40 | 41 | # Thumbnails 42 | ._* 43 | 44 | # Files that might appear in the root of a volume 45 | .DocumentRevisions-V100 46 | .fseventsd 47 | .Spotlight-V100 48 | .TemporaryItems 49 | .Trashes 50 | .VolumeIcon.icns 51 | .com.apple.timemachine.donotpresent 52 | 53 | # Directories potentially created on remote AFP share 54 | .AppleDB 55 | .AppleDesktop 56 | Network Trash Folder 57 | Temporary Items 58 | .apdisk 59 | 60 | # Eclipse project files 61 | .settings/ 62 | .classpath 63 | .project 64 | -------------------------------------------------------------------------------- /.reuse/dep5: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: enterprise-messaging-client-java-samples 3 | Upstream-Contact: 4 | Source: https://github.com/SAP-samples/enterprise-messaging-client-java-samples 5 | Disclaimer: The code in this project may include calls to APIs (“API Calls”) of 6 | SAP or third-party products or services developed outside of this project 7 | (“External Products”). 8 | “APIs” means application programming interfaces, as well as their respective 9 | specifications and implementing code that allows software to communicate with 10 | other software. 11 | API Calls to External Products are not licensed under the open source license 12 | that governs this project. The use of such API Calls and related External 13 | Products are subject to applicable additional agreements with the relevant 14 | provider of the External Products. In no event shall the open source license 15 | that governs this project grant any rights in or to any External Products,or 16 | alter, expand or supersede any terms of the applicable additional agreements. 17 | If you have a valid license agreement with SAP for the use of a particular SAP 18 | External Product, then you may make use of any API Calls included in this 19 | project’s code for that SAP External Product, subject to the terms of such 20 | license agreement. If you do not have a valid license agreement for the use of 21 | a particular SAP External Product, then you may only make use of any API Calls 22 | in this project for that SAP External Product for your internal, non-productive 23 | and non-commercial test and evaluation of such API Calls. Nothing herein grants 24 | you any rights to use or access any SAP External Product, or provide any third 25 | parties the right to use of access any SAP External Product, through API Calls. 26 | 27 | Files: * 28 | Copyright: 2018,2019,2020 SAP SE or an SAP affiliate company and enterprise-messaging-client-java-samples 29 | License: Apache-2.0 30 | -------------------------------------------------------------------------------- /CREDITS.txt: -------------------------------------------------------------------------------- 1 | This program references the following third party open source or other free download components. 2 | The third party licensors of these components may provide additional license rights, 3 | terms and conditions and/or require certain notices as described below. 4 | 5 | Apache log4j (http://logging.apache.org/log4j/1.2/) 6 | Licensed under Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | JUnit (http://www.junit.org/) 9 | Licensed under Common Public License - v 1.0 - http://junit.sourceforge.net/cpl-v10.html 10 | 11 | SLF4J (http://www.slf4j.org/) 12 | Licensed under MIT - http://www.slf4j.org/license.html 13 | 14 | Spring Framework (https://github.com/spring-projects/spring-framework) 15 | Licensed under Apache License, Version 2.0 - https://github.com/spring-projects/spring-framework/blob/master/src/docs/dist/license.txt -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSES/Apache-2.0.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 9 | 10 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 11 | 12 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 13 | 14 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 15 | 16 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 17 | 18 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 19 | 20 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 21 | 22 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 23 | 24 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 25 | 26 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 27 | 28 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 29 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 30 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 31 | (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and 32 | (b) You must cause any modified files to carry prominent notices stating that You changed the files; and 33 | (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 34 | (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 35 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 36 | 37 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 38 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 39 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 40 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 41 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 42 | END OF TERMS AND CONDITIONS 43 | 44 | APPENDIX: How to apply the Apache License to your work. 45 | 46 | To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. 47 | 48 | Copyright [yyyy] [name of copyright owner] 49 | 50 | Licensed under the Apache License, Version 2.0 (the "License"); 51 | you may not use this file except in compliance with the License. 52 | You may obtain a copy of the License at 53 | 54 | http://www.apache.org/licenses/LICENSE-2.0 55 | 56 | Unless required by applicable law or agreed to in writing, software 57 | distributed under the License is distributed on an "AS IS" BASIS, 58 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 59 | See the License for the specific language governing permissions and 60 | limitations under the License. 61 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Messaging Client Java - Samples for SAP Event Mesh 2 | 3 | image:https://api.reuse.software/info/github.com/SAP-samples/event-mesh-client-java-samples["REUSE status", link="https://api.reuse.software/info/github.com/SAP-samples/event-mesh-client-java-samples"] 4 | 5 | == Note 6 | The SAP Cloud Platform Enterprise Messaging service has been renamed to SAP Event Mesh - find more information in this link:https://blogs.sap.com/2021/02/22/please-welcome-sap-event-mesh-new-name-for-sap-cloud-platform-enterprise-messaging/[blog article]. 7 | 8 | == Description 9 | SAP Event Mesh provides a cloud-based messaging framework for the development of decoupled and resilient services and integration flows (using SAP Cloud Integration) to support asynchronous communication principles. 10 | Direct integration with SAP S/4HANA Business Event Handling allows efficient development of innovative and scaling extensions. 11 | 12 | This sample demonstrates Event Mesh with Java, using combinations of vanilla Java, Spring, and JMS. Details on each sample application and the covered scenario are described in the table _List of sample projects_ below. 13 | 14 | For more details of **SAP Event Mesh** take a look at the link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/df532e8735eb4322b00bfc7e42f84e8d.html[SAP Event Mesh on SAP Help portal]. 15 | 16 | 17 | == Requirements 18 | Below requirements are necessary for each of the samples. 19 | Further necessary configuration and settings are dependent on the specific sample and are documented within each sample project. 20 | 21 | * Installed _Java 8_ -> link:https://java.com/de/download/[Java download] 22 | * Installed _Git_ -> link:https://git-scm.com/downloads[Git download] 23 | * Installed _Maven 3.x_ -> link:https://maven.apache.org/download.cgi[Maven download] 24 | * A _SAP BTP_ Account with `Event Mesh Service` is required. + 25 | For more detailed information and help on how to start with _SAP Event Mesh_ please check the link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/df532e8735eb4322b00bfc7e42f84e8d.html[SAP help page]. 26 | ** Optional: Installed _CloudFoundry CLI_ -> link:https://docs.cloudfoundry.org/cf-cli/install-go-cli.html[Installing the cf CLI] 27 | *** This must be also fully configured with the corresponding Cloud Foundry landscape to be able to do a `cf push` 28 | ** Created Event Mesh Service Instance 29 | *** e.g. via cli: `cf cs enterprise-messaging default emjapi-samples-sapbtp -c` link:./emjapi-samples-jms-p2p/config/[``] 30 | *** The Service Descriptors can be found link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/d0483a9e38434f23a4579d6fcc72654b.html[here] 31 | *** Remember to adjust the manifest file of the application 32 | *** Include the ability to create required queues (e.g. `NameOfQueue`) and queue subscriptions (e.g. `NameOfTopic`) via e.g. 33 | link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/57af1bd4e8f54b0a9b36414a5ec6b800.html?q=messaging%20management[MM API], 34 | link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/57af1bd4e8f54b0a9b36414a5ec6b800.html[UI] 35 | 36 | === Recommended 37 | 38 | * Installed IDE of choice (e.g. link:https://code.visualstudio.com/[Visual Studio] with installed link:https://marketplace.visualstudio.com/items?itemName=redhat.java[Java language support] plugin) 39 | 40 | === List of sample projects 41 | 42 | [cols=3*,options=header] 43 | |=== 44 | |Application 45 | |Scenario 46 | |Scenario Description 47 | 48 | |link:./emjapi-samples-jms-p2p[`emjapi-samples-jms-p2p`] 49 | |Application for Event Mesh based on Spring Web running on SAP Business Technology Platform (@ CloudFoundry (with Event Mesh Service)). 50 | |This sample demonstrates how messages can be send and received from a SAP BTP deployed application. Therefore the messaging sample provides a _Spring Boot_ based application which provides REST endpoints for _send_ and _receive_ messages via a queue (or queues) of choice. The REST endpoints are provided via the `MessagingServiceRestController`. 51 | 52 | |link:./emjapi-samples-jms-pubsub[`emjapi-samples-jms-pubsub`] 53 | |Application for Event Mesh based on Spring Web running on SAP Business Technology Platform (@ CloudFoundry (with Event Mesh Service)). 54 | |This sample demonstrates how messages can be send and received from a topic from a SAP BTP deployed application. Therefore the messaging sample provides a _Spring Boot_ based application which provides REST endpoints for _send_ and _receive_ messages via a topic of choice. It also offers a REST endpoint to receive a message from a queue. The REST endpoints are provided via the `MessagingServiceRestController`. 55 | 56 | |=== 57 | 58 | == Download and Installation 59 | To download and install the samples just clone this repository via `git clone` 60 | 61 | For details on how to configure and run the samples please take a look into the README in the corresponding samples directory. 62 | 63 | == Usage of the client 64 | 65 | This section describes the usage of the client without any sample application. It is described which dependencies are needed and how a `MessagingServiceJmsConnectionFactory` is received in a short way. 66 | 67 | === Dependencies 68 | 69 | Three different dependencies are needed: 70 | 71 | . the emjapi spring service connector which provides the `MessagingService` 72 | . the emjapi core which creates the connection factory 73 | . the emjapi JMS extension which provides the `MessagingServiceJmsConnectionFactory` 74 | 75 | ```xml 76 | 77 | com.sap.cloud.servicesdk.xbem 78 | emjapi-connector-sap-cp 79 | ${version.xbem.client} 80 | 81 | 82 | 83 | com.sap.cloud.servicesdk.xbem 84 | emjapi-core 85 | ${version.xbem.client} 86 | 87 | 88 | 89 | com.sap.cloud.servicesdk.xbem 90 | emjapi-extension-sap-cp-jms 91 | ${version.xbem.client} 92 | 93 | ``` 94 | 95 | === Code snippets 96 | 97 | Get the `MessagingService` via the spring `Cloud` object 98 | 99 | ```java 100 | ServiceConnectorConfig config = null; // currently there are no configurations for the MessagingServiceFactory supported 101 | Cloud cloud = new CloudFactory().getCloud(); 102 | // get a messaging service factory via the service connector 103 | MessagingService messagingService = cloud.getSingletonServiceConnector(MessagingService.class, config); 104 | ``` 105 | 106 | Create a the `MessagingServiceFactory` object with the help of the `MessagingServiceFactoryCreator` and get a `MessagingServiceJmsConnectionFactory`. 107 | The Connection Factory can be configured with the `MessagingServiceJmsSettings`. In case the reconnection feature is not needed and an individual 108 | connection mechanism (e.G. through a connection cache) is used the settings can be skipped. The connection factory can be built with 109 | `messagingServiceFactory.createConnectionFactory(MessagingServiceJmsConnectionFactory.class,settings)`. 110 | 111 | ```java 112 | MessagingServiceJmsSettings settings = new MessagingServiceJmsSettings(); // settings are preset with default values (see JavaDoc) 113 | settings.setMaxReconnectAttempts(5); // use -1 for unlimited attempts 114 | settings.setInitialReconnectDelay(3000); 115 | settings.setReconnectDelay(3000); 116 | MessagingServiceFactory messagingServiceFactory = MessagingServiceFactoryCreator.createFactory(messagingService); 117 | MessagingServiceJmsConnectionFactory connectionFactory = messagingServiceFactory.createConnectionFactory(MessagingServiceJmsConnectionFactory.class, settings) 118 | ``` 119 | 120 | Further the `MessagingServiceJmsConnectionFactory` is used to create a connection and a session. 121 | 122 | ```java 123 | Connection connection = connectionFactory.createConnection(); 124 | Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)); 125 | ``` 126 | 127 | == Messaging Management API 128 | The messaging management api (MM API) provides functionality for creating, deleting and updating queues and queue subscriptions. 129 | Further more it provides APIs to get information on queues and queue subscriptions. 130 | The MM API documentation can be found link:https://help.sap.com/doc/75c9efd00fc14183abc4c613490c53f4/Cloud/en-US/rest-management-messaging.html[here]. 131 | The MM APIs have to be enabled in the service descriptor. A description for enabling the MM API can be found link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/d0483a9e38434f23a4579d6fcc72654b.html[here]. 132 | 133 | == Creation of queues with the UI 134 | Queues can be created through the SAP Business Technology Platform Cockpit UI. 135 | More information regarding the creation of queues through the UI can be found link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/57af1bd4e8f54b0a9b36414a5ec6b800.html[here] 136 | 137 | == Service Descriptor 138 | Examples for the different service descriptors can be found link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/d0483a9e38434f23a4579d6fcc72654b.html[here] on the help site 139 | and in the config folder of this project. 140 | 141 | == Contributing 142 | This project is _'as-is'_ with no support, no changes being made. + 143 | You are welcome to make changes to improve it but we are not available for questions or support of any kind. 144 | 145 | == Licensing 146 | Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved. + 147 | This project is licensed under the Apache Software License, version 2.0 except as noted otherwise in the link:./LICENSES/Apache-2.0.txt[LICENSE file]. 148 | -------------------------------------------------------------------------------- /emjapi-samples-jms-p2p/README.adoc: -------------------------------------------------------------------------------- 1 | = SAP Event Mesh JMS: Point to Point 2 | :toc: 3 | 4 | Sample application (plain Java) of how to use the JMS client to send and receive messages via SAP Event Mesh. 5 | 6 | == Prerequisites 7 | 8 | * Installed _Java 8_ -> link:https://java.com/de/download/[Java download] 9 | * Installed _Git_ -> link:https://git-scm.com/downloads[Git download] 10 | * Installed _Maven 3.x_ -> link:https://maven.apache.org/download.cgi[Maven download] 11 | * Optional: Installed Postman 12 | * A _SAP BTP_ Account with `Event Mesh Service` is required. + 13 | For more detailed information and help on how to start with _SAP Event Mesh_ please check the link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/df532e8735eb4322b00bfc7e42f84e8d.html[SAP help page]. 14 | ** Optional: Installed _CloudFoundry CLI_ -> link:https://docs.cloudfoundry.org/cf-cli/install-go-cli.html[Installing the cf CLI] 15 | *** This must be also fully configured with the corresponding Cloud Foundry landscape to be able to do a `cf push`. 16 | ** Created Event Mesh Service Instance 17 | *** e.g. via cli: `cf cs enterprise-messaging default emjapi-samples-sapbtp -c` link:./config/[`emjapi-samples-jms-p2p/config`] 18 | *** The Service Descriptors can be found link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/d0483a9e38434f23a4579d6fcc72654b.html[here] 19 | *** Remember to adjust the manifest file of the application 20 | ** Create queues (e.g. `NameOfQueue`) via e.g. link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/57af1bd4e8f54b0a9b36414a5ec6b800.html?q=messaging%20management[MM API], 21 | link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/57af1bd4e8f54b0a9b36414a5ec6b800.html[UI] 22 | *** For queue creation with the MM API you need to provide a fully qualified queue name including the namespace 23 | 24 | === Recommended 25 | 26 | * Installed IDE of choice (e.g. link:https://code.visualstudio.com/[Visual Studio] with installed link:https://marketplace.visualstudio.com/items?itemName=redhat.java[Java language support] plugin) 27 | 28 | == Project 29 | 30 | The point to point (p2p) sample is a small spring boot (version 2.0.6) applications which provides two different REST endpoints to send and receive messages from a specific queue. 31 | 32 | === Steps to Start 33 | 34 | . Check all _Prerequisites_ fulfilled (see section _Prerequisites_ above) 35 | . Clone the repository via `git clone` 36 | . Build the project with maven (`mvn clean install`) 37 | . Push to Cloud Foundry via `cf push` (*if the service was renamed please adopt the manifest accordingly*) 38 | 39 | === Steps to Use 40 | 41 | * The queue name has to be URL encoded. The samples provide a function to URL encode 42 | ** `curl -X POST -H "Content-Type: text/plain" -H "Cache-Control: no-cache" -d "https:///encode"`(the body must contain the queue name) 43 | * Send a message with a HTTP POST via https:///queue//message (the body must contain the message) 44 | ** `curl -X POST -H "Content-Type: text/plain" -H "Cache-Control: no-cache" -d '' "https:///queue//message"` 45 | * Receive a message with a HTTP GET via https:///queue//message 46 | ** Note that the this is a blocking call. If the request was aborted the consumer will still be active on the server and receive the next message. 47 | ** `curl -X GET -H "Content-Type: text/plain" -H "Cache-Control: no-cache" "https:///queue//message"` 48 | 49 | === Code Snippets 50 | 51 | [source,java] 52 | ---- 53 | ServiceConnectorConfig config = null; // currently there are no configurations for the MessagingServiceFactory supported 54 | Cloud cloud = new CloudFactory().getCloud(); 55 | // get a messaging service factory via the service connector 56 | MessagingService messagingService = cloud.getSingletonServiceConnector(MessagingService.class, config); 57 | ---- 58 | 59 | Create a the `MessagingServiceFactory` object with the help of the `MessagingServiceFactoryCreator` and get a `MessagingServiceJmsConnectionFactory`. 60 | The Connection Factory can be configured with the `MessagingServiceJmsSettings`. In case the reconnection feature is not needed and an individual 61 | connection mechanism (e.G. through a connection cache) is used the settings can be skipped. The connection factory can be built with 62 | `messagingServiceFactory.createConnectionFactory(MessagingServiceJmsConnectionFactory.class,settings)`. 63 | 64 | ```java 65 | MessagingServiceJmsSettings settings = new MessagingServiceJmsSettings(); // settings are preset with default values (see JavaDoc) 66 | settings.setMaxReconnectAttempts(5); // use -1 for unlimited attempts 67 | settings.setInitialReconnectDelay(3000); 68 | settings.setReconnectDelay(3000); 69 | MessagingServiceFactory messagingServiceFactory = MessagingServiceFactoryCreator.createFactory(messagingService); 70 | MessagingServiceJmsConnectionFactory connectionFactory = messagingServiceFactory.createConnectionFactory(MessagingServiceJmsConnectionFactory.class, settings) 71 | ``` 72 | 73 | ==== Sending 74 | For sending messages a `Connection` and a `Session` is needed first. Note that those resources must be closed if they are not needed anymore. As those objects are implementing the `autoclosable` interface they will be closed automatically after the try-catch-block. Now a `BytesMessage` can be created. In the next steps a queue is bound to a producer. They queue must be created on the broker first (via. e.g. the UI or MM API). Note, that the prefix "queue:" is mandatory. Finally, the message can be sent to the queue. 75 | 76 | 77 | ```java 78 | try (Connection connection = connectionFactory.createConnection();Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) { 79 | connection.start(); 80 | BytesMessage byteMessage = session.createBytesMessage(); 81 | byteMessage.writeBytes(message.getBytes()); 82 | Queue queue = session.createQueue("queue:" + ""); // even though the JMS API is "createQueue" the queue will not be created on the message broker 83 | MessageProducer producer = session.createProducer(queue); 84 | producer.send(byteMessage); 85 | } catch (JMSException e) { 86 | LOG.error("Could not send message={}.", message, e); 87 | } 88 | ``` 89 | ==== Receiving 90 | 91 | In this example a consumer is listening to a queue. Again a `Connection` and a `Session` is needed. Note that those resources must be closed if they are not needed anymore. First a queue with the mandatory prefix "queue:" is bound to consumer. As the messages are sent as a `ByteMassage` the message needs to be converted to e.g. a `String` 92 | 93 | ```java 94 | try (Connection connection = connectionFactory.createConnection();Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) { 95 | connection.start(); 96 | Queue queue = session.createQueue(QUEUE_PREFIX + queueName); // see comments above 97 | MessageConsumer consumer = session.createConsumer(queue); 98 | BytesMessage message = (BytesMessage) consumer.receive(); // Blocking call. Define a timeout or use a Message Listener 99 | byte[] byteData = new byte[(int) message.getBodyLength()]; 100 | message.readBytes(byteData); 101 | } catch (JMSException e) { 102 | LOG.error("Could not receive message.", e); 103 | } 104 | ``` 105 | 106 | == Messaging Management API 107 | The messaging management api (MM API) provides functionality for creating, deleting and updating queues and queue subscriptions. 108 | Further more it provides APIs to get information on queues and queue subscriptions. 109 | The MM API documentation can be found link:https://help.sap.com/doc/75c9efd00fc14183abc4c613490c53f4/Cloud/en-US/rest-management-messaging.html[here]. 110 | The MM APIs have to be enabled in the service descriptor. A description for enabling the MM API can be found link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/d0483a9e38434f23a4579d6fcc72654b.html[here]. 111 | 112 | == Creation of queues with the UI 113 | Queues can be created through the SAP Business Technology Platform Cockpit UI. 114 | More information regarding the creation of queues through the UI can be found link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/57af1bd4e8f54b0a9b36414a5ec6b800.html[here] 115 | 116 | == Service Descriptor 117 | Examples for the different service descriptors can be found link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/d0483a9e38434f23a4579d6fcc72654b.html[here] on the help site 118 | and in the config folder of this project. 119 | 120 | == Support 121 | This project is _'as-is'_ with no support, no changes being made. + 122 | You are welcome to make changes to improve it but we are not available for questions or support of any kind. 123 | 124 | 125 | == License 126 | Copyright (c) 2017 SAP SE or an SAP affiliate company. All rights reserved. 127 | This file is licensed under the _SAP SAMPLE CODE LICENSE AGREEMENT, v1.0-071618_ except as noted otherwise in the link:../LICENSE.txt[LICENSE file]. -------------------------------------------------------------------------------- /emjapi-samples-jms-p2p/config/em-config-default.json: -------------------------------------------------------------------------------- 1 | { 2 | "emname": "em-sample-default", 3 | "namespace": "sap/em/1", 4 | "options": { 5 | "management": true, 6 | "messagingrest": true, 7 | "messaging": true 8 | }, 9 | "rules": { 10 | "queueRules": { 11 | "inboundFilter": [ 12 | "${namespace}/#" 13 | ], 14 | "outboundFilter": [ 15 | "${namespace}/#" 16 | ] 17 | }, 18 | "topicRules": { 19 | "inboundFilter": [ 20 | "${namespace}/#" 21 | ], 22 | "outboundFilter": [ 23 | "${namespace}/#" 24 | ] 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /emjapi-samples-jms-p2p/config/em-config-dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "emname": "em-sample-dev", 3 | "options": { 4 | "management": true, 5 | "messagingrest": true, 6 | "messaging": true 7 | } 8 | } -------------------------------------------------------------------------------- /emjapi-samples-jms-p2p/manifest.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Default Manifest with single input for sample 3 | applications: 4 | - name: emjapi-samples-jms-p2p 5 | memory: 768M 6 | path: target/emjapi-samples-jms-p2p.jar 7 | random-route: false 8 | services: 9 | # This must point to an existing `event-mesh` service instance 10 | #- name: 11 | # parameters: 12 | # xsuaa: 13 | # credential-type: x509 14 | # x509: 15 | # validity: 7 16 | # validity-type: DAYS -------------------------------------------------------------------------------- /emjapi-samples-jms-p2p/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.springframework.boot 8 | spring-boot-starter-parent 9 | 2.6.4 10 | 11 | 12 | 13 | com.sap.cloud.samples.servicesdk.xbem 14 | emjapi-samples-jms-p2p 15 | 2.1.0 16 | jar 17 | 18 | SAP BTP EM: Basic p2p sample app with JMS ext. 19 | SAP Event Mesh - Java Client - Basic Sample application with JMS extension 20 | 21 | 22 | 23 | Sap Sample Code License Agreement 24 | https://github.com/SAP/enterprise-messaging-client-java-samples/raw/master/LICENSE.txt 25 | repo 26 | 27 | 28 | 29 | https://github.com/SAP/enterprise-messaging-client-java-samples 30 | 31 | 32 | UTF-8 33 | UTF-8 34 | 1.8 35 | 1.8 36 | 2.4.0 37 | 2.4.0 38 | 39 | 40 | 41 | 42 | 43 | com.sap.cloud.servicesdk.xbem 44 | emjapi-core 45 | ${version.xbem.client} 46 | 47 | 48 | 49 | com.sap.cloud.servicesdk.xbem 50 | emjapi-extension-sap-cp-jms 51 | ${version.xbem.client} 52 | 53 | 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-starter-web 58 | 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-starter-webflux 63 | 64 | 65 | 66 | io.pivotal.cfenv 67 | java-cfenv-boot 68 | ${version.pivotal.cf.env} 69 | 70 | 71 | 72 | 73 | junit 74 | junit 75 | test 76 | 77 | 78 | 79 | 80 | ${project.artifactId} 81 | 82 | 83 | org.springframework.boot 84 | spring-boot-maven-plugin 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /emjapi-samples-jms-p2p/src/main/java/com/sap/xbem/sample/sapcp/jms/p2p/Application.java: -------------------------------------------------------------------------------- 1 | package com.sap.xbem.sample.sapcp.jms.p2p; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 7 | import org.springframework.web.util.UrlPathHelper; 8 | 9 | @SpringBootApplication 10 | public class Application implements WebMvcConfigurer { 11 | 12 | public static void main(String[] args) { 13 | System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true"); 14 | SpringApplication.run(Application.class, args); 15 | } 16 | 17 | // Necessary for allowing encoded path segments 18 | @Override 19 | public void configurePathMatch(PathMatchConfigurer configurer) { 20 | UrlPathHelper urlPathHelper = new UrlPathHelper(); 21 | urlPathHelper.setUrlDecode(false); 22 | configurer.setUrlPathHelper(urlPathHelper); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /emjapi-samples-jms-p2p/src/main/java/com/sap/xbem/sample/sapcp/jms/p2p/config/MessagingServiceConfig.java: -------------------------------------------------------------------------------- 1 | package com.sap.xbem.sample.sapcp.jms.p2p.config; 2 | 3 | import com.sap.cloud.servicesdk.xbem.core.MessagingServiceFactory; 4 | import com.sap.cloud.servicesdk.xbem.core.exception.MessagingException; 5 | import com.sap.cloud.servicesdk.xbem.core.impl.MessagingServiceFactoryCreator; 6 | import com.sap.cloud.servicesdk.xbem.extension.sapcp.jms.MessagingServiceJmsConnectionFactory; 7 | import com.sap.cloud.servicesdk.xbem.extension.sapcp.jms.MessagingServiceJmsSettings; 8 | import io.pivotal.cfenv.core.CfCredentials; 9 | import io.pivotal.cfenv.core.CfEnv; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | import java.util.Map; 14 | 15 | @Configuration 16 | public class MessagingServiceConfig { 17 | 18 | @Bean 19 | public MessagingServiceFactory getMessagingServiceFactory() { 20 | CfEnv cfEnv = new CfEnv(); 21 | CfCredentials cfCredentials = cfEnv.findCredentialsByName(""); 22 | Map credentials = cfCredentials.getMap(); 23 | if (credentials == null) { 24 | throw new IllegalStateException("Unable to create the MessagingService."); 25 | } 26 | return MessagingServiceFactoryCreator.createFactoryFromCredentials(credentials); 27 | } 28 | 29 | @Bean 30 | public MessagingServiceJmsConnectionFactory getMessagingServiceJmsConnectionFactory(MessagingServiceFactory messagingServiceFactory) { 31 | try { 32 | /* 33 | * The settings object is preset with default values (see JavaDoc) 34 | * and can be adjusted. The settings aren't required and depend on 35 | * the use-case. Note: a connection will be closed after an idle 36 | * time of 5 minutes. 37 | */ 38 | MessagingServiceJmsSettings settings = new MessagingServiceJmsSettings(); 39 | settings.setFailoverMaxReconnectAttempts(5); // use -1 for unlimited attempts 40 | settings.setFailoverInitialReconnectDelay(3000); 41 | settings.setFailoverReconnectDelay(3000); 42 | settings.setJmsRequestTimeout(30000); 43 | settings.setAmqpIdleTimeout(-1); 44 | 45 | // Custom provided authentication request, it is not mandatory. Emjapi can request token from the client info. 46 | //TokenRequest tokenRequest = new TokenRequest(); 47 | //settings.setAuthenticationRequest(tokenRequest::requestToken); 48 | 49 | return messagingServiceFactory.createConnectionFactory(MessagingServiceJmsConnectionFactory.class, settings); 50 | } catch (MessagingException e) { 51 | throw new IllegalStateException("Unable to create the Connection Factory", e); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /emjapi-samples-jms-p2p/src/main/java/com/sap/xbem/sample/sapcp/jms/p2p/config/TokenRequest.java: -------------------------------------------------------------------------------- 1 | package com.sap.xbem.sample.sapcp.jms.p2p.config; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | import com.sap.cloud.servicesdk.xbem.core.MessagingService; 5 | import io.pivotal.cfenv.core.CfCredentials; 6 | import io.pivotal.cfenv.core.CfEnv; 7 | import org.springframework.http.MediaType; 8 | import org.springframework.util.LinkedMultiValueMap; 9 | import org.springframework.util.MultiValueMap; 10 | import org.springframework.web.reactive.function.BodyInserters; 11 | import org.springframework.web.reactive.function.client.WebClient; 12 | 13 | public class TokenRequest { 14 | 15 | private final WebClient webClient; 16 | private final MultiValueMap formData = new LinkedMultiValueMap<>(); 17 | 18 | public TokenRequest() { 19 | CfEnv cfEnv = new CfEnv(); 20 | CfCredentials cfCredentials = cfEnv.findCredentialsByName(""); 21 | MessagingService messagingServiceClientInfo = new MessagingService.MessagingServiceBuilder().fromCredentials(cfCredentials.getMap()).build(); 22 | 23 | String endpoint = messagingServiceClientInfo.getOAuthTokenEndpoint(); 24 | String clientId = messagingServiceClientInfo.getClientId(); 25 | String clientSecret = messagingServiceClientInfo.getClientSecret(); 26 | 27 | webClient = WebClient.builder().baseUrl(endpoint).build(); 28 | 29 | formData.add("client_id", clientId); 30 | formData.add("client_secret", clientSecret); 31 | formData.add("grant_type", "client_credentials"); 32 | formData.add("response", "token"); 33 | } 34 | 35 | public String requestToken() { 36 | JsonNode tokenResponse = webClient.post().contentType(MediaType.APPLICATION_FORM_URLENCODED).accept( 37 | MediaType.APPLICATION_JSON).body(BodyInserters.fromFormData(formData)).retrieve().bodyToMono(JsonNode.class).block(); 38 | return tokenResponse.get("access_token").textValue(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /emjapi-samples-jms-p2p/src/main/java/com/sap/xbem/sample/sapcp/jms/p2p/services/MessagingServiceRestController.java: -------------------------------------------------------------------------------- 1 | package com.sap.xbem.sample.sapcp.jms.p2p.services; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.net.URLDecoder; 5 | import java.net.URLEncoder; 6 | import java.nio.charset.StandardCharsets; 7 | 8 | import javax.jms.BytesMessage; 9 | import javax.jms.Connection; 10 | import javax.jms.JMSException; 11 | import javax.jms.MessageConsumer; 12 | import javax.jms.MessageProducer; 13 | import javax.jms.Queue; 14 | import javax.jms.Session; 15 | 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.http.HttpStatus; 20 | import org.springframework.http.ResponseEntity; 21 | import org.springframework.web.bind.annotation.GetMapping; 22 | import org.springframework.web.bind.annotation.PathVariable; 23 | import org.springframework.web.bind.annotation.PostMapping; 24 | import org.springframework.web.bind.annotation.RequestBody; 25 | import org.springframework.web.bind.annotation.RestController; 26 | 27 | import com.sap.cloud.servicesdk.xbem.core.exception.MessagingException; 28 | import com.sap.cloud.servicesdk.xbem.extension.sapcp.jms.MessagingServiceJmsConnectionFactory; 29 | 30 | @RestController(MessagingServiceRestController.ROOT_PATH) 31 | public class MessagingServiceRestController { 32 | 33 | private static final Logger LOG = LoggerFactory.getLogger(MessagingServiceRestController.class); 34 | public static final String ROOT_PATH = "/"; 35 | private static final String QUEUE_PATH = "queue/{queueName}"; 36 | private static final String MESSAGE_PATH = "/message"; 37 | private static final String ENCODED_PATH = "encode"; 38 | private static final String MESSAGE_REST_PATH = QUEUE_PATH + MESSAGE_PATH; 39 | private static final String MESSAGE_ENCODING_REST_PATH = ENCODED_PATH; 40 | 41 | private static final String QUEUE_PREFIX = "queue:"; // mandatory prefix for connection to a queue. Note that you must not create a queue on the broker with this prefix 42 | 43 | private final MessagingServiceJmsConnectionFactory connectionFactory; 44 | 45 | @Autowired 46 | private MessagingServiceRestController(MessagingServiceJmsConnectionFactory messagingServiceJmsConnectionFactory) { 47 | this.connectionFactory = messagingServiceJmsConnectionFactory; 48 | } 49 | 50 | /** 51 | * Convenient method to encode a value. 52 | * 53 | * @param value 54 | * value to encode 55 | * @return encoded value 56 | * @throws UnsupportedEncodingException 57 | */ 58 | @PostMapping(MESSAGE_ENCODING_REST_PATH) 59 | public ResponseEntity encodeValue(@RequestBody String value) throws UnsupportedEncodingException { 60 | String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); 61 | return new ResponseEntity(encodedValue, HttpStatus.OK); 62 | } 63 | 64 | /** 65 | * Send a message to a queue. The queue must be created via e.G. the 66 | * Dashboard of the enterprise-messaging-service first. 67 | * 68 | * @param message 69 | * @param queueName 70 | * @return the message and the topic which has been sent 71 | * @throws MessagingException 72 | */ 73 | @PostMapping(MESSAGE_REST_PATH) 74 | public ResponseEntity sendMessage(@RequestBody String message, @PathVariable String queueName) throws MessagingException { 75 | try { 76 | queueName = decodeValue(queueName); 77 | } catch (UnsupportedEncodingException e1) { 78 | return ResponseEntity.badRequest().body("Unable to decode the queuename"); 79 | } 80 | 81 | LOG.info("Sending message={} to queue={}", message, queueName); 82 | try (Connection connection = connectionFactory.createConnection(); 83 | Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) { 84 | connection.start(); 85 | BytesMessage byteMessage = session.createBytesMessage(); 86 | byteMessage.writeBytes(message.getBytes()); 87 | Queue queue = session.createQueue(QUEUE_PREFIX + queueName); // even though the JMS API is "createQueue" the queue will not be created on the message broker 88 | MessageProducer producer = session.createProducer(queue); 89 | producer.send(byteMessage); 90 | return ResponseEntity.status(HttpStatus.CREATED).body("message=" + message + " sent to queue=" + queueName); 91 | } catch (JMSException e) { 92 | LOG.error("Could not send message={}.", message, e); 93 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Could not send message. Error=" + e); 94 | } 95 | } 96 | 97 | /** 98 | * Receives a message from a queue. The rest call will block until a message 99 | * is received. 100 | * 101 | * @param queueName 102 | * @return the message which has been received 103 | * @throws MessagingException 104 | */ 105 | @GetMapping(MESSAGE_REST_PATH) 106 | public ResponseEntity receiveMessage(@PathVariable String queueName) throws MessagingException { 107 | try { 108 | queueName = decodeValue(queueName); 109 | } catch (UnsupportedEncodingException e1) { 110 | return ResponseEntity.badRequest().body("Unable to decode the queuename"); 111 | } 112 | 113 | /* 114 | * create the connection and the session, don't forget to close those 115 | * resources if you're not using autoclosable 116 | * 117 | * you can also switch the acknowledgment mode in the session to e.G. 118 | * Session.CLIENT_ACKNOWLEDGE. Remember to acknowledge the message by 119 | * yourself then: byteMessage.acknowledge(). 120 | */ 121 | try (Connection connection = connectionFactory.createConnection(); 122 | Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) { // see comments above 123 | connection.start(); 124 | Queue queue = session.createQueue(QUEUE_PREFIX + queueName); // see comments above 125 | MessageConsumer consumer = session.createConsumer(queue); 126 | BytesMessage message = (BytesMessage) consumer.receive(); // Blocking call. You can either define a timeout or use a message listener 127 | byte[] byteData = new byte[(int) message.getBodyLength()]; 128 | message.readBytes(byteData); 129 | return ResponseEntity.ok(new String(byteData)); 130 | } catch (JMSException e) { 131 | LOG.error("Could not receive message.", e); 132 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Could not receive message. Error=" + e); 133 | } 134 | } 135 | 136 | private String decodeValue(String value) throws UnsupportedEncodingException { 137 | return URLDecoder.decode(value, StandardCharsets.UTF_8.toString()); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /emjapi-samples-jms-p2p/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | P2P Sample for Event Mesh Java API (emjapi) 7 | 8 | 9 | 10 |

P2P Sample for Event Mesh Java API (emjapi)

11 | 12 | 13 | -------------------------------------------------------------------------------- /emjapi-samples-jms-pubsub/README.adoc: -------------------------------------------------------------------------------- 1 | = SAP Event Mesh JMS: Publish and Subscribe 2 | :toc: 3 | 4 | Sample application of how to use the JMS client to send and receive messages using a topic via SAP Event Mesh. 5 | 6 | == Prerequisites 7 | 8 | * Installed _Java 8_ -> link:https://java.com/de/download/[Java download] 9 | * Installed _Git_ -> link:https://git-scm.com/downloads[Git download] 10 | * Installed _Maven 3.x_ -> link:https://maven.apache.org/download.cgi[Maven download] 11 | * Optional: Installed Postman 12 | * A _SAP BTP_ Account with `Event Mesh Service` is required. + 13 | For more detailed information and help on how to start with _SAP Event Mesh_ please check the link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/df532e8735eb4322b00bfc7e42f84e8d.html[SAP help page]. 14 | ** Optional: Installed _CloudFoundry CLI_ -> link:https://docs.cloudfoundry.org/cf-cli/install-go-cli.html[Installing the cf CLI] 15 | *** This must be also fully configured with the corresponding Cloud Foundry landscape to be able to do a `cf push`. 16 | ** Created Event Mesh Service Instance 17 | *** e.g. via cli: `cf cs enterprise-messaging default emjapi-samples-sapbtp -c` link:./config/[``] 18 | *** The Service Descriptors can be found link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/d0483a9e38434f23a4579d6fcc72654b.html[here] 19 | *** Remember to adjust the manifest file of the application 20 | ** Create queues (e.g. `NameOfQueue`) and subscribe a queue to a topic of choice (e.g. `NameOfTopic`) via e.g. link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/57af1bd4e8f54b0a9b36414a5ec6b800.html?q=messaging%20management[MM API], 21 | link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/57af1bd4e8f54b0a9b36414a5ec6b800.html[UI] 22 | *** For queue creation with the MM API you need to provide a fully qualified queue name including the namespace 23 | 24 | === Recommended 25 | 26 | * Installed IDE of choice (e.g. link:https://code.visualstudio.com/[Visual Studio] with installed link:https://marketplace.visualstudio.com/items?itemName=redhat.java[Java language support] plugin) 27 | 28 | == Project 29 | 30 | The publish and subscribe (pubsub) sample is a small spring boot (version 2.0.6) applications which provides three different REST endpoints to send and receive messages from a topic. 31 | 32 | === Steps to Start 33 | 34 | . Check all _Prerequisites_ fulfilled (see section _Prerequisites_ above) 35 | . Clone the repository via `git clone` 36 | . Build the project with maven (`mvn clean install`) 37 | . Push to Cloud Foundry via `cf push` (*if the service was renamed please adopt the manifest accordingly*) 38 | 39 | === Steps to Use 40 | 41 | * The queue name has to be URL encoded. The samples provide a function to URL encode 42 | ** `curl -X POST -H "Content-Type: text/plain" -H "Cache-Control: no-cache" -d "https:///encode"`(the body must contain the queue name) 43 | * Send a message with a HTTP POST via https:///topic//message (The body must contain the message) 44 | ** Note that a client or a queue must be subscribed to the topic before 45 | ** The queue name has to be url encoded. The 46 | ** `curl -X POST -H "Content-Type: text/plain" -H "Cache-Control: no-cache" -d '' "https:///topic//message"` 47 | * Receive a message via a queue with a HTTP GET via https:///queue//message 48 | ** Note that a queue subscription is needed before. A queue subscription can be created via e.G. the UI. 49 | ** `curl -X GET -H "Content-Type: text/plain" -H "Cache-Control: no-cache" "https:///queue//message"` 50 | 51 | === Code Snippets 52 | 53 | In order to use the messaging service the spring cloud service connector can be used to receive a `MessagingServiceFactory`. 54 | 55 | ```java 56 | ServiceConnectorConfig config = null; // currently there are no configurations for the MessagingServiceFactory supported 57 | Cloud cloud = new CloudFactory().getCloud(); 58 | // get a messaging service factory via the service connector 59 | MessagingService messagingService = cloud.getSingletonServiceConnector(MessagingService.class, config); 60 | ``` 61 | 62 | Create a the `MessagingServiceFactory` object with the help of the `MessagingServiceFactoryCreator` and get a `MessagingServiceJmsConnectionFactory`. 63 | The Connection Factory can be configured with the `MessagingServiceJmsSettings`. In case the reconnection feature is not needed and an individual 64 | connection mechanism (e.G. through a connection cache) is used the settings can be skipped. The connection factory can be built with 65 | `messagingServiceFactory.createConnectionFactory(MessagingServiceJmsConnectionFactory.class,settings)`. 66 | 67 | ```java 68 | MessagingServiceJmsSettings settings = new MessagingServiceJmsSettings(); // settings are preset with default values (see JavaDoc) 69 | settings.setMaxReconnectAttempts(5); // use -1 for unlimited attempts 70 | settings.setInitialReconnectDelay(3000); 71 | settings.setReconnectDelay(3000); 72 | MessagingServiceFactory messagingServiceFactory = MessagingServiceFactoryCreator.createFactory(messagingService); 73 | MessagingServiceJmsConnectionFactory connectionFactory = messagingServiceFactory.createConnectionFactory(MessagingServiceJmsConnectionFactory.class, settings) 74 | ``` 75 | 76 | ==== Sending 77 | For sending messages a `Connection` and a `Session` is needed first. Note that those resources must be closed if they are not needed anymore. As those objects are implementing the `autoclosable` interface they will be closed automatically after the try-catch-block. Now a `BytesMessage` can be created. In the next steps a topic is bound (not created) to a producer. Note, that the prefix "topic:" is mandatory. Finally, the message can be sent to the topic. 78 | 79 | ```java 80 | try (Connection connection = connectionFactory.createConnection();Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) { 81 | connection.start(); 82 | Topic topic = session.createTopic("topic:" + ""); 83 | BytesMessage byteMessage = session.createBytesMessage(); 84 | byteMessage.writeBytes(message.getBytes()); 85 | MessageProducer producer = session.createProducer(topic); 86 | producer.send(byteMessage); 87 | } catch (JMSException e) { 88 | LOG.error("Could not send message={}.", message, e); 89 | } 90 | ``` 91 | 92 | ==== Receiving 93 | Currently direct topic subscription is *not supported for the plan default*. 94 | In this example a consumer is subscribed to a specific topic. Again a `Connection` and a `Session` is needed. Note that those resources must be closed if they are not needed anymore. First a topic (not created) with the mandatory prefix "topic:" is bound to consumer. As the messages are sent as a `ByteMassage` the message needs to be converted to e.g. a `String` 95 | 96 | 97 | ```java 98 | try (Connection connection = connectionFactory.createConnection();Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) { 99 | connection.start(); 100 | Topic topic = session.createTopic(TOPIC_PREFIX + topicName); 101 | MessageConsumer consumer = session.createConsumer(topic); 102 | // Blocking call. Define a timeout or use a Message Listener 103 | BytesMessage message = (BytesMessage) consumer.receive(); 104 | byte[] byteData = new byte[(int) message.getBodyLength()]; 105 | message.readBytes(byteData); 106 | } catch (JMSException e) { 107 | LOG.error("Could not receive message.", e); 108 | } 109 | ``` 110 | 111 | == Messaging Management API 112 | The messaging management api (MM API) provides functionality for creating, deleting and updating queues and queue subscriptions. 113 | Further more it provides APIs to get information on queues and queue subscriptions. 114 | The MM API documentation can be found link:https://help.sap.com/doc/75c9efd00fc14183abc4c613490c53f4/Cloud/en-US/rest-management-messaging.html[here]. 115 | The MM APIs have to be enabled in the service descriptor. A description for enabling the MM API can be found link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/d0483a9e38434f23a4579d6fcc72654b.html[here]. 116 | 117 | == Creation of queues with the UI 118 | Queues can be created through the SAP Business Technology Platform Cockpit UI. 119 | More information regarding the creation of queues through the UI can be found link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/57af1bd4e8f54b0a9b36414a5ec6b800.html[here] 120 | 121 | == Service Descriptor 122 | Examples for the different service descriptors can be found link:https://help.sap.com/viewer/bf82e6b26456494cbdd197057c09979f/Cloud/en-US/d0483a9e38434f23a4579d6fcc72654b.html[here] on the help site 123 | and in the config folder of this project. 124 | 125 | == Support 126 | This project is _'as-is'_ with no support, no changes being made. + 127 | You are welcome to make changes to improve it but we are not available for questions or support of any kind. 128 | 129 | 130 | == License 131 | Copyright (c) 2017 SAP SE or an SAP affiliate company. All rights reserved. 132 | This file is licensed under the _SAP SAMPLE CODE LICENSE AGREEMENT, v1.0-071618_ except as noted otherwise in the link:../LICENSE.txt[LICENSE file]. -------------------------------------------------------------------------------- /emjapi-samples-jms-pubsub/config/em-config-default.json: -------------------------------------------------------------------------------- 1 | { 2 | "emname": "em-sample-default", 3 | "namespace": "sap/em/1", 4 | "options": { 5 | "management": true, 6 | "messagingrest": true, 7 | "messaging": true 8 | }, 9 | "rules": { 10 | "queueRules": { 11 | "inboundFilter": [ 12 | "${namespace}/#" 13 | ], 14 | "outboundFilter": [ 15 | "${namespace}/#" 16 | ] 17 | }, 18 | "topicRules": { 19 | "inboundFilter": [ 20 | "${namespace}/#" 21 | ], 22 | "outboundFilter": [ 23 | "${namespace}/#" 24 | ] 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /emjapi-samples-jms-pubsub/config/em-config-dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "emname": "em-sample-dev", 3 | "options": { 4 | "management": true, 5 | "messagingrest": true, 6 | "messaging": true 7 | } 8 | } -------------------------------------------------------------------------------- /emjapi-samples-jms-pubsub/manifest.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Default Manifest with single input for sample 3 | applications: 4 | - name: emjapi-samples-jms-pubsub 5 | memory: 768M 6 | path: target/emjapi-samples-jms-pubsub.jar 7 | random-route: false 8 | services: 9 | # This must point to an existing `event-mesh` service instance 10 | #- name: 11 | # parameters: 12 | # xsuaa: 13 | # credential-type: x509 14 | # x509: 15 | # validity: 7 16 | # validity-type: DAYS -------------------------------------------------------------------------------- /emjapi-samples-jms-pubsub/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.springframework.boot 8 | spring-boot-starter-parent 9 | 2.6.4 10 | 11 | 12 | 13 | com.sap.cloud.samples.servicesdk.xbem 14 | emjapi-samples-jms-pubsub 15 | 2.1.0 16 | jar 17 | 18 | SAP CP EM: Basic p2p sample app with JMS ext. 19 | SAP Cloud Platform Enterprise Messaging - Java Client - Basic Sample application with JMS extension 20 | 21 | 22 | 23 | Sap Sample Code License Agreement 24 | https://github.com/SAP/enterprise-messaging-client-java-samples/raw/master/LICENSE.txt 25 | repo 26 | 27 | 28 | 29 | https://github.com/SAP/enterprise-messaging-client-java-samples 30 | 31 | 32 | UTF-8 33 | UTF-8 34 | 1.8 35 | 1.8 36 | 2.4.0 37 | 2.4.0 38 | 39 | 40 | 41 | 42 | 43 | com.sap.cloud.servicesdk.xbem 44 | emjapi-core 45 | ${version.xbem.client} 46 | 47 | 48 | 49 | com.sap.cloud.servicesdk.xbem 50 | emjapi-extension-sap-cp-jms 51 | ${version.xbem.client} 52 | 53 | 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-starter-web 58 | 59 | 60 | 61 | io.pivotal.cfenv 62 | java-cfenv-boot 63 | ${version.pivotal.cf.env} 64 | 65 | 66 | 67 | 68 | junit 69 | junit 70 | test 71 | 72 | 73 | 74 | 75 | ${project.artifactId} 76 | 77 | 78 | org.springframework.boot 79 | spring-boot-maven-plugin 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /emjapi-samples-jms-pubsub/src/main/java/com/sap/xbem/sample/sapcp/jms/p2p/Application.java: -------------------------------------------------------------------------------- 1 | package com.sap.xbem.sample.sapcp.jms.p2p; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 7 | import org.springframework.web.util.UrlPathHelper; 8 | 9 | @SpringBootApplication 10 | public class Application implements WebMvcConfigurer { 11 | 12 | public static void main(String[] args) { 13 | System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true"); 14 | SpringApplication.run(Application.class, args); 15 | } 16 | 17 | // Necessary for allowing encoded path segments 18 | @Override 19 | public void configurePathMatch(PathMatchConfigurer configurer) { 20 | UrlPathHelper urlPathHelper = new UrlPathHelper(); 21 | urlPathHelper.setUrlDecode(false); 22 | configurer.setUrlPathHelper(urlPathHelper); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /emjapi-samples-jms-pubsub/src/main/java/com/sap/xbem/sample/sapcp/jms/p2p/config/MessagingServiceConfig.java: -------------------------------------------------------------------------------- 1 | package com.sap.xbem.sample.sapcp.jms.p2p.config; 2 | 3 | import com.sap.cloud.servicesdk.xbem.core.MessagingServiceFactory; 4 | import com.sap.cloud.servicesdk.xbem.core.exception.MessagingException; 5 | import com.sap.cloud.servicesdk.xbem.core.impl.MessagingServiceFactoryCreator; 6 | import com.sap.cloud.servicesdk.xbem.extension.sapcp.jms.MessagingServiceJmsConnectionFactory; 7 | import com.sap.cloud.servicesdk.xbem.extension.sapcp.jms.MessagingServiceJmsSettings; 8 | import io.pivotal.cfenv.core.CfCredentials; 9 | import io.pivotal.cfenv.core.CfEnv; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | import java.util.Map; 14 | 15 | @Configuration 16 | public class MessagingServiceConfig { 17 | 18 | @Bean 19 | public MessagingServiceFactory getMessagingServiceFactory() { 20 | CfEnv cfEnv = new CfEnv(); 21 | CfCredentials cfCredentials = cfEnv.findCredentialsByName(""); 22 | Map credentials = cfCredentials.getMap(); 23 | if (credentials == null) { 24 | throw new IllegalStateException("Unable to create the MessagingService."); 25 | } 26 | return MessagingServiceFactoryCreator.createFactoryFromCredentials(credentials); 27 | } 28 | 29 | @Bean 30 | public MessagingServiceJmsConnectionFactory getMessagingServiceJmsConnectionFactory(MessagingServiceFactory messagingServiceFactory) { 31 | try { 32 | /* 33 | * The settings object is preset with default values (see JavaDoc) 34 | * and can be adjusted. The settings aren't required and depend on 35 | * the use-case. Note: a connection will be closed after an idle 36 | * time of 5 minutes. 37 | */ 38 | MessagingServiceJmsSettings settings = new MessagingServiceJmsSettings(); 39 | settings.setFailoverMaxReconnectAttempts(5); // use -1 for unlimited attempts 40 | settings.setFailoverInitialReconnectDelay(3000); 41 | settings.setFailoverReconnectDelay(3000); 42 | settings.setJmsRequestTimeout(30000); 43 | settings.setAmqpIdleTimeout(-1); 44 | 45 | // Custom provided authentication request, it is not mandatory. Emjapi can request token from the client info. 46 | //TokenRequest tokenRequest = new TokenRequest(); 47 | //settings.setAuthenticationRequest(tokenRequest::requestToken); 48 | 49 | return messagingServiceFactory.createConnectionFactory(MessagingServiceJmsConnectionFactory.class, settings); 50 | } catch (MessagingException e) { 51 | throw new IllegalStateException("Unable to create the Connection Factory", e); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /emjapi-samples-jms-pubsub/src/main/java/com/sap/xbem/sample/sapcp/jms/p2p/services/MessagingServiceRestController.java: -------------------------------------------------------------------------------- 1 | package com.sap.xbem.sample.sapcp.jms.p2p.services; 2 | 3 | import com.sap.cloud.servicesdk.xbem.extension.sapcp.jms.MessagingServiceJmsConnectionFactory; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import javax.jms.*; 12 | import java.io.UnsupportedEncodingException; 13 | import java.net.URLDecoder; 14 | import java.net.URLEncoder; 15 | import java.nio.charset.StandardCharsets; 16 | 17 | @RestController(MessagingServiceRestController.ROOT_PATH) 18 | public class MessagingServiceRestController { 19 | 20 | private static final Logger LOG = LoggerFactory.getLogger(MessagingServiceRestController.class); 21 | public static final String ROOT_PATH = "/"; 22 | private static final String TOPIC_PATH = "topic/{topicName}/"; 23 | private static final String QUEUE_PATH = "queue/{queueName}/"; 24 | private static final String MESSAGE_PATH = "message"; 25 | private static final String ENCODED_PATH = "encode"; 26 | private static final String MESSAGE_TOPIC_REST_PATH = TOPIC_PATH + MESSAGE_PATH; 27 | private static final String MESSAGE_QUEUE_REST_PATH = QUEUE_PATH + MESSAGE_PATH; 28 | private static final String MESSAGE_ENCODING_REST_PATH = ENCODED_PATH; 29 | 30 | private static final String TOPIC_PREFIX = "topic:"; // mandatory prefix to bind a topic. 31 | private static final String QUEUE_PREFIX = "queue:"; // mandatory prefix to bind a queue. Note that you must not create a queue on the broker with this prefix! 32 | 33 | private final MessagingServiceJmsConnectionFactory connectionFactory; 34 | 35 | @Autowired 36 | private MessagingServiceRestController(MessagingServiceJmsConnectionFactory messagingServiceJmsConnectionFactory) { 37 | this.connectionFactory = messagingServiceJmsConnectionFactory; 38 | } 39 | 40 | /** 41 | * Convenient method to encode a value. 42 | * 43 | * @param value value to encode 44 | * @return encoded value 45 | */ 46 | @PostMapping(MESSAGE_ENCODING_REST_PATH) 47 | public ResponseEntity encodeValue(@RequestBody String value) throws UnsupportedEncodingException { 48 | String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); 49 | return new ResponseEntity<>(encodedValue, HttpStatus.OK); 50 | } 51 | 52 | /** 53 | * Publishes a message to a given topic. 54 | * 55 | * @param message to publish 56 | * @param topicName where message will be published 57 | * @return the message and the topic which has been sent 58 | */ 59 | @PostMapping(MESSAGE_TOPIC_REST_PATH) 60 | public ResponseEntity sendMessage(@RequestBody String message, @PathVariable String topicName) { 61 | try { 62 | topicName = decodeValue(topicName); 63 | } catch (UnsupportedEncodingException e1) { 64 | return ResponseEntity.badRequest().body("Unable to decode the queuename"); 65 | } 66 | 67 | LOG.info("Sending message={} to topic={}", message, topicName); 68 | try (Connection connection = connectionFactory.createConnection(); 69 | Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) { 70 | connection.start(); 71 | Topic topic = session.createTopic(TOPIC_PREFIX + topicName); 72 | BytesMessage byteMessage = session.createBytesMessage(); 73 | byteMessage.writeBytes(message.getBytes()); 74 | MessageProducer producer = session.createProducer(topic); 75 | producer.send(byteMessage); 76 | return ResponseEntity.status(HttpStatus.CREATED).body("message=" + message + " sent to topic=" + topicName); 77 | } catch (JMSException e) { 78 | LOG.error("Could not send message={} to topic={}.", message, topicName, e); 79 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Could not send message. Error=" + e); 80 | } 81 | } 82 | 83 | /** 84 | * Receives a message from a queue. This example is supposed to be a publish 85 | * and subscribe scenario. Please create a queue subscription via e.G. the 86 | * Dashboard first. 87 | * 88 | * @param queueName name of the queue where message will receive 89 | * @return the message which has been received 90 | */ 91 | @GetMapping(MESSAGE_QUEUE_REST_PATH) 92 | public ResponseEntity receiveMessageFromQueue(@PathVariable String queueName) { 93 | try { 94 | queueName = decodeValue(queueName); 95 | } catch (UnsupportedEncodingException e1) { 96 | return ResponseEntity.badRequest().body("Unable to decode the queuename"); 97 | } 98 | /* 99 | * create connection and session, don't forget to close those resources 100 | * if you're not using autoclosable 101 | * 102 | * you can also switch the acknowledgment mode in the session to e.G. 103 | * Session.CLIENT_ACKNOWLEDGE. Remember to acknowledge the message by 104 | * yourself then: byteMessage.acknowledge(). 105 | */ 106 | try (Connection connection = connectionFactory.createConnection(); 107 | Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) { // see comments above 108 | connection.start(); 109 | // even though the JMS API is "createQueue" the queue will not be created on the message broker 110 | Queue queue = session.createQueue(QUEUE_PREFIX + queueName); 111 | MessageConsumer consumer = session.createConsumer(queue); 112 | BytesMessage message = (BytesMessage) consumer.receive(); // Blocking call. You can either define a timeout or use a message listener 113 | byte[] byteData = new byte[(int) message.getBodyLength()]; 114 | message.readBytes(byteData); 115 | return ResponseEntity.ok(new String(byteData)); 116 | } catch (JMSException e) { 117 | LOG.error("Could not receive message.", e); 118 | LOG.error("Could not receive message from queue={}.", queueName, e); 119 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Could not receive message from queue. Error=" + e); 120 | } 121 | } 122 | 123 | private String decodeValue(String value) throws UnsupportedEncodingException { 124 | return URLDecoder.decode(value, StandardCharsets.UTF_8.toString()); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /emjapi-samples-jms-pubsub/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Pub Sub Sample for Event Mesh Java API (emjapi) 7 | 8 | 9 | 10 |

Pub Sub Sample for Event Mesh Java API (emjapi)

11 | 12 | 13 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.sap.cloud.samples.servicesdk.xbem 8 | emjapi-samples 9 | 2.1.0 10 | pom 11 | 12 | SAP BTP EM: Several samples for Java client 13 | SAP Event Mesh - Java Client - Several samples to run with or on SAP Business Technology Platform 14 | 15 | 16 | 17 | Sap Sample Code License Agreement 18 | https://github.com/SAP/enterprise-messaging-client-java-samples/raw/master/LICENSE.txt 19 | repo 20 | 21 | 22 | 23 | https://github.com/SAP/enterprise-messaging-client-java-samples 24 | 25 | 26 | emjapi-samples-jms-p2p 27 | emjapi-samples-jms-pubsub 28 | 29 | 30 | 31 | UTF-8 32 | UTF-8 33 | 1.8 34 | 1.8 35 | 36 | 37 | 38 | package 39 | 40 | 41 | --------------------------------------------------------------------------------