├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE.md
├── README.md
├── astra.json
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
└── main
├── java
└── com
│ └── datastax
│ └── astra
│ ├── GettingStartedWithAstra.java
│ ├── controller
│ ├── ControllerExceptionHandler.java
│ ├── CredentialsController.java
│ ├── InstrumentsController.java
│ └── SpacecraftController.java
│ ├── dao
│ ├── SessionManager.java
│ ├── SpacecraftInstrumentsDao.java
│ ├── SpacecraftInstrumentsQueryProvider.java
│ ├── SpacecraftJourneyDao.java
│ └── SpacecraftMapper.java
│ ├── doc
│ ├── DocumentationApiConfiguration.java
│ └── DocumentationController.java
│ ├── entity
│ ├── AbstractInstrumentReading.java
│ ├── LocationUdt.java
│ ├── SpacecraftJourneyCatalog.java
│ ├── SpacecraftLocationOverTime.java
│ ├── SpacecraftPressureOverTime.java
│ ├── SpacecraftSpeedOverTime.java
│ └── SpacecraftTemperatureOverTime.java
│ ├── model
│ └── PagedResultWrapper.java
│ ├── service
│ └── AstraService.java
│ └── utils
│ └── CqlFileUtils.java
└── resources
├── application.conf
├── application.yml
├── banner.txt
├── logback.xml
└── schema.cql
/.gitignore:
--------------------------------------------------------------------------------
1 | # eclipse conf file
2 | .settings
3 | .classpath
4 | .project
5 | .cache
6 |
7 | # idea conf files
8 | .idea
9 | *.ipr
10 | *.iws
11 | *.iml
12 |
13 | # building
14 | target
15 | build
16 | tmp
17 | dist
18 |
19 | # misc
20 | .DS_Store
21 |
22 | .factorypath
23 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at . All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | When contributing to this repository, please first discuss the change you wish to make via issue,
4 | email, or any other method with the owners of this repository before making a change.
5 |
6 | Please note we have a [Code of Conduct](CODE_OF_CONDUCT.md), please follow it in all your interactions with the project.
7 |
8 | ## Found an Issue?
9 | If you find a bug in the source code or a mistake in the documentation, you can help us by
10 | [submitting an issue](#submit-issue) to the GitHub Repository. Even better, you can
11 | [submit a Pull Request](#submit-pr) with a fix.
12 |
13 | ## Want a Feature?
14 | You can *request* a new feature by [submitting an issue](#submit-issue) to the GitHub
15 | Repository. If you would like to *implement* a new feature, please submit an issue with
16 | a proposal for your work first, to be sure that we can use it.
17 |
18 | * **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
19 |
20 | ## Contribution Guidelines
21 |
22 | ### Submitting an Issue
23 | Before you submit an issue, search the archive, maybe your question was already answered.
24 |
25 | If your issue appears to be a bug, and hasn't been reported, open a new issue.
26 | Help us to maximize the effort we can spend fixing issues and adding new
27 | features, by not reporting duplicate issues. Providing the following information will increase the
28 | chances of your issue being dealt with quickly:
29 |
30 | * **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps
31 | * **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you
32 | * **Reproduce the Error** - provide a live example or a unambiguous set of steps
33 | * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be
34 | causing the problem (line of code or commit)
35 |
36 | ### Submitting a Pull Request (PR)
37 | Before you submit your Pull Request (PR) consider the following guidelines:
38 |
39 | * Search the repository (https://github.com/bechbd/[repository-name]/pulls) for an open or closed PR that relates to your submission. You don't want to duplicate effort.
40 |
41 | * Create a fork of the repo
42 | * Navigate to the repo you want to fork
43 | * In the top right corner of the page click **Fork**:
44 | 
45 |
46 | * Make your changes in the forked repo
47 | * Commit your changes using a descriptive commit message
48 | * In GitHub, create a pull request: https://help.github.com/en/articles/creating-a-pull-request-from-a-fork
49 | * If we suggest changes then:
50 | * Make the required updates.
51 | * Rebase your fork and force push to your GitHub repository (this will update your Pull Request):
52 |
53 | ```shell
54 | git rebase master -i
55 | git push -f
56 | ```
57 |
58 | That's it! Thank you for your contribution!
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:11
2 |
3 | MAINTAINER Cedrick Lunven
4 |
5 | ########################################################
6 | ## Environment Variables
7 | ########################################################
8 |
9 | VOLUME /tmp
10 | ARG JAR_FILE
11 | ADD ${JAR_FILE} app.jar
12 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
13 |
14 | # Exposing expected port by WEBUI
15 | EXPOSE 8080
16 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Getting Started with Apache Cassandra™ and Java using DataStax Astra DB
3 | *50 minutes, Intermediate, [Start Building](https://github.com/DataStax-Examples/getting-started-with-astra-java#prerequisites)*
4 |
5 | This provides an example REST backend built in Java using `Spring Boot` for use with the [Getting Started with Astra UI](https://github.com/DataStax-Examples/getting-started-with-astra-ui).
6 |
7 |
8 |
9 | 
10 |
11 |
12 | ## Objectives
13 | * How to connect to Astra DB via the Secure Connect Bundle
14 | * How to manage a Cassandra Session within a JAVA web application
15 |
16 | ## How this Works
17 | This is an example of a Spring Boot Microservice for use with the Astra Getting Started UI which is found [here](https://github.com/DataStax-Examples/getting-started-with-astra-ui).
18 |
19 | ## Get Started
20 | To build and play with this app, follow the build instructions that are located here: [https://github.com/DataStax-Examples/getting-started-with-astra-java](https://github.com/DataStax-Examples/getting-started-with-astra-java#prerequisites)
21 |
22 |
23 | ## Prerequisites
24 | Let's do some initial setup by creating a serverless(!) database.
25 |
26 | ### DataStax Astra
27 | 1. Create a [DataStax Astra account](https://dtsx.io/3zBltF7) if you don't already have one:
28 | 
29 |
30 | 2. On the home page. Locate the button **`Create Database`**
31 | 
32 |
33 | 3. Locate the **`Get Started`** button to continue
34 | 
35 |
36 | 4. Define a **database name**, **keyspace name** and select a database **region**, then click **create database**.
37 | 
38 |
39 | 5. Your Astra DB will be ready when the status will change from *`Pending`* to **`Active`** 💥💥💥
40 | 
41 |
42 | 6. After your database is provisioned, we need to generate an Application Token for our App. Go to the `Settings` tab in the database home screen.
43 | 
44 |
45 | 7. Select `Admin User` for the role for this Sample App and then generate the token. Download the CSV so that we can use the credentials we need later.
46 | 
47 |
48 | 8. After you have your Application Token, head to the database connect screen and select the driver connection that we need. Go ahead and download the `Secure Bundle` for the driver.
49 | 
50 |
51 | 9. Make note of where to use the `Client Id` and `Client Secret` that is part of the Application Token that we generated earlier.
52 | 
53 |
54 | ### Github
55 | 1. Click `Use this template` at the top of the [GitHub Repository](https://github.com/DataStax-Examples/getting-started-with-astra-java):
56 | 
57 |
58 | 2. Enter a repository name and click 'Create repository from template':
59 | 
60 |
61 | 3. Clone the repository:
62 | 
63 |
64 | ## 🚀 Getting Started Paths:
65 | *Make sure you've completed the [prerequisites](#prerequisites) before starting this step*
66 | - [Running on your local machine](#running-on-your-local-machine)
67 |
68 | ### Running on your local machine
69 | Make sure that you have:
70 | * Java 11
71 | * An Astra DB compatible Java driver, instructions may be found [here](https://docs.datastax.com/en/astra/docs/connect/drivers/connect-java.html) to install this locally.
72 | * An Astra database with the CQL schema located in [schema.cql](https://raw.githubusercontent.com/DataStax-Examples/getting-started-with-astra-java/master/src/main/resources/schema.cql) already added.
73 | * The username, password, keyspace name, and secure connect bundle downloaded from your Astra DB. For information on how to obtain these credentials please read the documentation found [here](https://docs.datastax.com/en/astra/docs/connect/secure-connect-bundle.html)
74 |
75 | This application is a Spring Boot web application. This sample can be run from the root directory using:
76 | ```sh
77 | cd getting-started-with-astra-java
78 |
79 | mvn spring-boot:run
80 | ```
81 |
82 | This will startup the application running on `http://localhost:8080`
83 |
84 | You will know that you are up and working when you get the following in your terminal window:
85 | ```sh
86 | 16:23:01.569 INFO com.datastax.astra.GettingStartedWithAstra : Started GettingStartedWithAstra in 1.851 seconds (JVM running for 2.39)
87 | ```
88 |
89 | #### Access the API documentation from a browser
90 |
91 | [http://localhost:8080](http://localhost:8080)
92 |
93 | *Note: If you want to change the listening port of the application, locate the file `src/main/resources/application.yml` and change key `server.port`*
94 |
95 | #### Setup the user interface to use this backend
96 | To setup the UI to connect to Java backend define a `.env` file in the `getting-started-with-astra-ui` project main directory. Inside the file it should have one entry pointing to this project's API endpoint:
97 | ```sh
98 | BASE_ADDRESS=http://localhost:8080/api
99 | ```
100 | Once you start that project with a `npm run build` it will point the UI to the backend API which will then be using Astra DB as a database. When you first connect to the UI, a dialog box will open asking for Astra DB connection information.
101 |
102 |
--------------------------------------------------------------------------------
/astra.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Getting Started with Java + Spring + Astra DB",
3 | "description": "This provides an example REST backend built in Java using Spring Boot for use with the Getting Started with Astra UI.",
4 | "duration": "50 minutes",
5 | "skillLevel": "Intermediate",
6 | "githubUrl": "https://github.com/DataStax-Examples/getting-started-with-astra-java",
7 | "tags": [
8 | { "name": "labs", "color": "warning" },
9 | { "name": "java" },
10 | { "name": "spring" },
11 | { "name": "java driver" }
12 | ],
13 | "category": "apps",
14 | "priority": 3,
15 | "heroImage": "https://raw.githubusercontent.com/DataStax-Examples/sample-app-template/master/screenshots/astra-sample-app-default.png"
16 | }
17 |
--------------------------------------------------------------------------------
/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven2 Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /etc/mavenrc ] ; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ] ; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false;
51 | darwin=false;
52 | mingw=false
53 | case "`uname`" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true;;
56 | Darwin*) darwin=true
57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
59 | if [ -z "$JAVA_HOME" ]; then
60 | if [ -x "/usr/libexec/java_home" ]; then
61 | export JAVA_HOME="`/usr/libexec/java_home`"
62 | else
63 | export JAVA_HOME="/Library/Java/Home"
64 | fi
65 | fi
66 | ;;
67 | esac
68 |
69 | if [ -z "$JAVA_HOME" ] ; then
70 | if [ -r /etc/gentoo-release ] ; then
71 | JAVA_HOME=`java-config --jre-home`
72 | fi
73 | fi
74 |
75 | if [ -z "$M2_HOME" ] ; then
76 | ## resolve links - $0 may be a link to maven's home
77 | PRG="$0"
78 |
79 | # need this for relative symlinks
80 | while [ -h "$PRG" ] ; do
81 | ls=`ls -ld "$PRG"`
82 | link=`expr "$ls" : '.*-> \(.*\)$'`
83 | if expr "$link" : '/.*' > /dev/null; then
84 | PRG="$link"
85 | else
86 | PRG="`dirname "$PRG"`/$link"
87 | fi
88 | done
89 |
90 | saveddir=`pwd`
91 |
92 | M2_HOME=`dirname "$PRG"`/..
93 |
94 | # make it fully qualified
95 | M2_HOME=`cd "$M2_HOME" && pwd`
96 |
97 | cd "$saveddir"
98 | # echo Using m2 at $M2_HOME
99 | fi
100 |
101 | # For Cygwin, ensure paths are in UNIX format before anything is touched
102 | if $cygwin ; then
103 | [ -n "$M2_HOME" ] &&
104 | M2_HOME=`cygpath --unix "$M2_HOME"`
105 | [ -n "$JAVA_HOME" ] &&
106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
107 | [ -n "$CLASSPATH" ] &&
108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
109 | fi
110 |
111 | # For Migwn, ensure paths are in UNIX format before anything is touched
112 | if $mingw ; then
113 | [ -n "$M2_HOME" ] &&
114 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
115 | [ -n "$JAVA_HOME" ] &&
116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
117 | # TODO classpath?
118 | fi
119 |
120 | if [ -z "$JAVA_HOME" ]; then
121 | javaExecutable="`which javac`"
122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
123 | # readlink(1) is not available as standard on Solaris 10.
124 | readLink=`which readlink`
125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
126 | if $darwin ; then
127 | javaHome="`dirname \"$javaExecutable\"`"
128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
129 | else
130 | javaExecutable="`readlink -f \"$javaExecutable\"`"
131 | fi
132 | javaHome="`dirname \"$javaExecutable\"`"
133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
134 | JAVA_HOME="$javaHome"
135 | export JAVA_HOME
136 | fi
137 | fi
138 | fi
139 |
140 | if [ -z "$JAVACMD" ] ; then
141 | if [ -n "$JAVA_HOME" ] ; then
142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
143 | # IBM's JDK on AIX uses strange locations for the executables
144 | JAVACMD="$JAVA_HOME/jre/sh/java"
145 | else
146 | JAVACMD="$JAVA_HOME/bin/java"
147 | fi
148 | else
149 | JAVACMD="`which java`"
150 | fi
151 | fi
152 |
153 | if [ ! -x "$JAVACMD" ] ; then
154 | echo "Error: JAVA_HOME is not defined correctly." >&2
155 | echo " We cannot execute $JAVACMD" >&2
156 | exit 1
157 | fi
158 |
159 | if [ -z "$JAVA_HOME" ] ; then
160 | echo "Warning: JAVA_HOME environment variable is not set."
161 | fi
162 |
163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
164 |
165 | # traverses directory structure from process work directory to filesystem root
166 | # first directory with .mvn subdirectory is considered project base directory
167 | find_maven_basedir() {
168 |
169 | if [ -z "$1" ]
170 | then
171 | echo "Path not specified to find_maven_basedir"
172 | return 1
173 | fi
174 |
175 | basedir="$1"
176 | wdir="$1"
177 | while [ "$wdir" != '/' ] ; do
178 | if [ -d "$wdir"/.mvn ] ; then
179 | basedir=$wdir
180 | break
181 | fi
182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
183 | if [ -d "${wdir}" ]; then
184 | wdir=`cd "$wdir/.."; pwd`
185 | fi
186 | # end of workaround
187 | done
188 | echo "${basedir}"
189 | }
190 |
191 | # concatenates all lines of a file
192 | concat_lines() {
193 | if [ -f "$1" ]; then
194 | echo "$(tr -s '\n' ' ' < "$1")"
195 | fi
196 | }
197 |
198 | BASE_DIR=`find_maven_basedir "$(pwd)"`
199 | if [ -z "$BASE_DIR" ]; then
200 | exit 1;
201 | fi
202 |
203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
204 | echo $MAVEN_PROJECTBASEDIR
205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
206 |
207 | # For Cygwin, switch paths to Windows format before running java
208 | if $cygwin; then
209 | [ -n "$M2_HOME" ] &&
210 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
211 | [ -n "$JAVA_HOME" ] &&
212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
213 | [ -n "$CLASSPATH" ] &&
214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
215 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
217 | fi
218 |
219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
220 |
221 | exec "$JAVACMD" \
222 | $MAVEN_OPTS \
223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
226 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
84 | @REM Fallback to current working directory if not found.
85 |
86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
88 |
89 | set EXEC_DIR=%CD%
90 | set WDIR=%EXEC_DIR%
91 | :findBaseDir
92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
93 | cd ..
94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
95 | set WDIR=%CD%
96 | goto findBaseDir
97 |
98 | :baseDirFound
99 | set MAVEN_PROJECTBASEDIR=%WDIR%
100 | cd "%EXEC_DIR%"
101 | goto endDetectBaseDir
102 |
103 | :baseDirNotFound
104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
105 | cd "%EXEC_DIR%"
106 |
107 | :endDetectBaseDir
108 |
109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
110 |
111 | @setlocal EnableExtensions EnableDelayedExpansion
112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
114 |
115 | :endReadAdditionalConfig
116 |
117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
118 |
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
123 | if ERRORLEVEL 1 goto error
124 | goto end
125 |
126 | :error
127 | set ERROR_CODE=1
128 |
129 | :end
130 | @endlocal & set ERROR_CODE=%ERROR_CODE%
131 |
132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
136 | :skipRcPost
137 |
138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
140 |
141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
142 |
143 | exit /B %ERROR_CODE%
144 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.datastax.astra
8 | getting-started-with-astra-java
9 | 1.0.0-SNAPSHOT
10 | getting-started-with-astra-java
11 | Sample Application to work with Astra
12 | jar
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.1.9.RELEASE
18 |
19 |
20 |
21 |
22 | 8
23 | 4.6.0
24 | 2.9.2
25 | 3.8.1
26 | 1.4.12
27 | UTF-8
28 |
29 |
30 |
31 |
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-starter-web
36 |
37 |
38 |
39 |
40 | io.springfox
41 | springfox-swagger2
42 | ${swagger.version}
43 |
44 |
45 | io.springfox
46 | springfox-swagger-ui
47 | ${swagger.version}
48 |
49 |
50 |
51 |
52 | com.datastax.oss
53 | java-driver-core
54 | ${java-driver.version}
55 |
56 |
57 | com.datastax.oss
58 | java-driver-query-builder
59 | ${java-driver.version}
60 |
61 |
62 | com.datastax.oss
63 | java-driver-mapper-runtime
64 | ${java-driver.version}
65 |
66 |
67 |
68 |
69 | org.apache.commons
70 | commons-lang3
71 |
72 |
73 | com.fasterxml.jackson.datatype
74 | jackson-datatype-jsr310
75 |
76 |
77 | commons-fileupload
78 | commons-fileupload
79 | 1.3.3
80 |
81 |
82 | org.apache.commons
83 | commons-io
84 | 1.3.2
85 |
86 |
87 |
88 |
89 | org.springframework.boot
90 | spring-boot-configuration-processor
91 | true
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | org.springframework.boot
101 | spring-boot-maven-plugin
102 |
103 |
104 |
105 | com.spotify
106 | dockerfile-maven-plugin
107 | ${version.maven.plugin.docker}
108 |
109 | clunven/getting-started-with-astra-java
110 |
111 | target/${project.build.finalName}.jar
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | org.apache.maven.plugins
121 | maven-compiler-plugin
122 | ${version.maven.plugin.compiler}
123 |
124 |
125 |
126 | com.datastax.oss
127 | java-driver-mapper-processor
128 | ${java-driver.version}
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 | datastax-releases-public-local
140 | https://repo.datastax.com/datastax-public-releases-local/
141 |
142 | true
143 |
144 |
145 | false
146 |
147 |
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/GettingStartedWithAstra.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Jeff Carpenter
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.datastax.astra;
17 |
18 | import org.springframework.boot.SpringApplication;
19 | import org.springframework.boot.autoconfigure.SpringBootApplication;
20 |
21 | @SpringBootApplication
22 | public class GettingStartedWithAstra {
23 |
24 | public static void main(String[] args) {
25 | SpringApplication.run(GettingStartedWithAstra.class, args);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/controller/ControllerExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.controller;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.http.HttpStatus;
6 | import org.springframework.web.bind.annotation.ControllerAdvice;
7 | import org.springframework.web.bind.annotation.ExceptionHandler;
8 | import org.springframework.web.bind.annotation.ResponseStatus;
9 |
10 | @ControllerAdvice
11 | public class ControllerExceptionHandler {
12 |
13 | /** Logger for the class. */
14 | private static final Logger LOGGER = LoggerFactory.getLogger(ControllerExceptionHandler.class);
15 |
16 | @ExceptionHandler(value = IllegalArgumentException.class)
17 | @ResponseStatus(value = HttpStatus.BAD_REQUEST)
18 | public String handleBadRequest(IllegalArgumentException ex) {
19 | LOGGER.error("Illegal Argument : {}", ex.getMessage());
20 | return ex.getMessage();
21 | }
22 |
23 | @ExceptionHandler(value = IllegalStateException.class)
24 | @ResponseStatus(value = HttpStatus.UNAUTHORIZED)
25 | public String handleUnAuthorized(IllegalStateException ex) {
26 | LOGGER.error("Illegal State : {}", ex.getMessage());
27 | return ex.getMessage();
28 | }
29 |
30 | @ExceptionHandler(value = RuntimeException.class)
31 | @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
32 | public String handleDefaultError(RuntimeException ex) {
33 | LOGGER.error("Default Error : {}", ex.getMessage());
34 | return ex.getMessage();
35 | }
36 |
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/controller/CredentialsController.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.controller;
2 |
3 | import static org.springframework.web.bind.annotation.RequestMethod.GET;
4 |
5 | import java.io.File;
6 | import java.io.IOException;
7 | import java.nio.file.Files;
8 | import java.nio.file.StandardCopyOption;
9 | import java.util.UUID;
10 |
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 | import org.springframework.http.MediaType;
14 | import org.springframework.http.ResponseEntity;
15 | import org.springframework.web.bind.annotation.CrossOrigin;
16 | import org.springframework.web.bind.annotation.PostMapping;
17 | import org.springframework.web.bind.annotation.RequestMapping;
18 | import org.springframework.web.bind.annotation.RequestParam;
19 | import org.springframework.web.bind.annotation.RestController;
20 | import org.springframework.web.multipart.MultipartFile;
21 |
22 | import com.datastax.astra.dao.SessionManager;
23 |
24 | import io.swagger.annotations.Api;
25 | import io.swagger.annotations.ApiImplicitParam;
26 | import io.swagger.annotations.ApiImplicitParams;
27 | import io.swagger.annotations.ApiOperation;
28 | import io.swagger.annotations.ApiParam;
29 | import io.swagger.annotations.ApiResponse;
30 | import io.swagger.annotations.ApiResponses;
31 | @CrossOrigin
32 | @RestController
33 | @Api(
34 | value = "/api/credentials",
35 | description = "Send connectivity parameters to initialize component")
36 | @RequestMapping("/api/credentials")
37 | public class CredentialsController {
38 |
39 | /** Logger for the class. */
40 | private static final Logger LOGGER = LoggerFactory.getLogger(CredentialsController.class);
41 |
42 | /**
43 | * POST on /api/credentials
44 | *
45 | * Request body is the zipfile
46 | *
47 | * @param username
48 | * HTTP POST PARAM user name
49 | * @param password
50 | * HTTP POST PARAM password
51 | * @param keyspace
52 | * name of keysapce
53 | * @return
54 | * status of connection
55 | * @throws IOException
56 | * cannot process incoming file
57 | */
58 | @PostMapping
59 | @ApiOperation(value = "Save credentials and initiate connection", response = String.class)
60 | @ApiResponses({
61 | @ApiResponse(code = 200, message = "Credentials are saved and system is now connected"),
62 | @ApiResponse(code = 401, message = "Invalid Credentials"),
63 | @ApiResponse(code = 400, message = "Invalid or missing parameters"),
64 | @ApiResponse(code = 500, message = "Internal error - cannot save file")
65 | })
66 | @ApiImplicitParams({
67 | @ApiImplicitParam(
68 | name = "file",
69 | value = "A binary zip file provided by astra to initiate a 2-ways SSL connection",
70 | required = true, dataType = "file", paramType = "form")
71 | })
72 | public ResponseEntity saveCredentials(
73 | @RequestParam("username")
74 | @ApiParam(name="username", value="login for user authentication", required=true)
75 | String username,
76 | @RequestParam("password")
77 | @ApiParam(name="password", value="password for user authentication", required=true)
78 | String password,
79 | @RequestParam("keyspace")
80 | @ApiParam(name="keyspace", value="keyspace to use", required=true)
81 | String keyspace,
82 | @RequestParam("file") MultipartFile file) throws IOException {
83 | LOGGER.info("Initializing credentials and connection");
84 | LOGGER.info("+ Zip File found with {} bytes", file.getSize());
85 |
86 | // Save File Locally in temp folder with generated UID
87 | File tempFile = File.createTempFile(UUID.randomUUID().toString(), ".zip");
88 | Files.copy(file.getInputStream(), tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
89 | LOGGER.info("+ Creating temporary file {}", tempFile.getAbsolutePath());
90 |
91 | SessionManager.getInstance()
92 | .saveCredentials(username, password, keyspace, tempFile.getAbsolutePath());
93 | LOGGER.info("+ Saving credentials into SessionManager");
94 |
95 | // Checking connection
96 | return checkConnection();
97 | }
98 |
99 | /**
100 | * Check if system is initialized and connected.
101 | */
102 | @RequestMapping(method = GET)
103 | @ApiOperation(value = "Status for component", response = String.class)
104 | @ApiResponses({
105 | @ApiResponse(code = 200, message = "System is connected"),
106 | @ApiResponse(code = 401, message = "Invalid Credentials or not initialized")
107 | })
108 | public ResponseEntity checkConnection() {
109 | SessionManager.getInstance().checkConnection();
110 | LOGGER.info("Session is successfully initialized and connected");
111 | return ResponseEntity.ok("Connection Successful");
112 | }
113 |
114 | @PostMapping(value = "/test", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
115 | public ResponseEntity testCredentials(
116 | @RequestParam("username") String username,
117 | @RequestParam("password") String password,
118 | @RequestParam("keyspace") String keyspace,
119 | @RequestParam("file") MultipartFile file) throws IOException {
120 |
121 | File tempFile = File.createTempFile(UUID.randomUUID().toString(), ".zip");
122 | Files.copy(file.getInputStream(), tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
123 | LOGGER.info("+ Creating temporary file {}", tempFile.getAbsolutePath());
124 |
125 | SessionManager.getInstance().testCredentials(username, password, keyspace, tempFile.getAbsolutePath());
126 | LOGGER.info("Session has been successfully established");
127 |
128 | return ResponseEntity.ok("Valid Parameters");
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/controller/InstrumentsController.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.controller;
2 |
3 | import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
4 |
5 | import java.util.List;
6 | import java.util.Optional;
7 | import java.util.UUID;
8 |
9 | import org.slf4j.Logger;
10 | import org.slf4j.LoggerFactory;
11 | import org.springframework.http.ResponseEntity;
12 | import org.springframework.web.bind.annotation.CrossOrigin;
13 | import org.springframework.web.bind.annotation.GetMapping;
14 | import org.springframework.web.bind.annotation.PathVariable;
15 | import org.springframework.web.bind.annotation.PostMapping;
16 | import org.springframework.web.bind.annotation.RequestBody;
17 | import org.springframework.web.bind.annotation.RequestMapping;
18 | import org.springframework.web.bind.annotation.RequestParam;
19 | import org.springframework.web.bind.annotation.RestController;
20 |
21 | import com.datastax.astra.entity.SpacecraftLocationOverTime;
22 | import com.datastax.astra.entity.SpacecraftPressureOverTime;
23 | import com.datastax.astra.entity.SpacecraftSpeedOverTime;
24 | import com.datastax.astra.entity.SpacecraftTemperatureOverTime;
25 | import com.datastax.astra.model.PagedResultWrapper;
26 | import com.datastax.astra.service.AstraService;
27 |
28 | import io.swagger.annotations.Api;
29 | import io.swagger.annotations.ApiOperation;
30 | import io.swagger.annotations.ApiParam;
31 | import io.swagger.annotations.ApiResponse;
32 |
33 | @CrossOrigin
34 | @RestController
35 | @Api(
36 | value = "api/spacecraft/{spacecraftName}/{journeyId}/instruments",
37 | description = "Works with Instruments")
38 | @RequestMapping("api/spacecraft/{spacecraftName}/{journeyId}/instruments")
39 | public class InstrumentsController {
40 |
41 | /** Logger for the class. */
42 | private static final Logger LOGGER = LoggerFactory.getLogger(InstrumentsController.class);
43 |
44 | /** Service implementation Injection. */
45 | private AstraService astraService;
46 |
47 | /**
48 | * Constructor.
49 | *
50 | * @param spacecraftService
51 | * service implementation
52 | */
53 | public InstrumentsController(AstraService astraService) {
54 | this.astraService = astraService;
55 | }
56 |
57 | /**
58 | * Retrieve temperature metrics
59 | */
60 | @GetMapping(value="/temperature", produces = APPLICATION_JSON_VALUE)
61 | @ApiOperation(value = "Retrieve temperature reading for a journey", response = List.class)
62 | @ApiResponse(code = 200, message = "Retrieve temperature reading for a journey")
63 | public ResponseEntity> getTemperatureReading(
64 | @ApiParam(name="spacecraftName", value="Spacecraft name",example = "gemini3",required=true )
65 | @PathVariable(value = "spacecraftName") String spacecraftName,
66 | @ApiParam(name="journeyId", value="Identifer for journey",example = "abb7c000-c310-11ac-8080-808080808080",required=true )
67 | @PathVariable(value = "journeyId") UUID journeyId,
68 | @ApiParam(name="pagesize", value="Requested page size, default is 10", required=false )
69 | @RequestParam("pagesize") Optional pageSize,
70 | @ApiParam(name="pagestate", value="Use to retrieve next pages", required=false )
71 | @RequestParam("pagestate") Optional pageState) {
72 | LOGGER.debug("Retrieving temperature readings for spacecraft {} and journey {}", spacecraftName, journeyId);
73 | PagedResultWrapper res = astraService.getTemperatureReading(spacecraftName, journeyId, pageSize, pageState);
74 | return ResponseEntity.ok(res);
75 | }
76 |
77 | /**
78 | * Retrieve pressure metrics
79 | */
80 | @GetMapping(value="/pressure", produces = APPLICATION_JSON_VALUE)
81 | @ApiOperation(value = "Retrieve pressure reading for a journey", response = List.class)
82 | @ApiResponse(code = 200, message = "Retrieve pressure reading for a journey")
83 | public ResponseEntity> getPressureReading(
84 | @ApiParam(name="spacecraftName", value="Spacecraft name",example = "gemini3",required=true )
85 | @PathVariable(value = "spacecraftName") String spacecraftName,
86 | @ApiParam(name="journeyId", value="Identifer for journey",example = "abb7c000-c310-11ac-8080-808080808080",required=true )
87 | @PathVariable(value = "journeyId") UUID journeyId,
88 | @ApiParam(name="pagesize", value="Requested page size, default is 10", required=false )
89 | @RequestParam("pagesize") Optional pageSize,
90 | @ApiParam(name="pagestate", value="Use to retrieve next pages", required=false )
91 | @RequestParam("pagestate") Optional pageState) {
92 | LOGGER.debug("Retrieving pressure readings for spacecraft {} and journey {}", spacecraftName, journeyId);
93 | return ResponseEntity.ok(astraService.getPressureReading(spacecraftName, journeyId, pageSize, pageState));
94 | }
95 |
96 | /**
97 | * Retrieve speed metrics
98 | */
99 | @GetMapping(value="/speed", produces = APPLICATION_JSON_VALUE)
100 | @ApiOperation(value = "Retrieve speed reading for a journey", response = List.class)
101 | @ApiResponse(code = 200, message = "Retrieve speed reading for a journey")
102 | public ResponseEntity> getSpeedReading(
103 | @ApiParam(name="spacecraftName", value="Spacecraft name",example = "gemini3",required=true )
104 | @PathVariable(value = "spacecraftName") String spacecraftName,
105 | @ApiParam(name="journeyId", value="Identifer for journey",example = "abb7c000-c310-11ac-8080-808080808080",required=true )
106 | @PathVariable(value = "journeyId") UUID journeyId,
107 | @ApiParam(name="pagesize", value="Requested page size, default is 10", required=false )
108 | @RequestParam("pagesize") Optional pageSize,
109 | @ApiParam(name="pagestate", value="Use to retrieve next pages", required=false )
110 | @RequestParam("pagestate") Optional pageState) {
111 | LOGGER.debug("Retrieving pressure readings for spacecraft {} and journey {}", spacecraftName, journeyId);
112 | return ResponseEntity.ok(astraService.getSpeedReading(spacecraftName, journeyId, pageSize, pageState));
113 | }
114 |
115 | /**
116 | * Retrieve location metrics
117 | */
118 | @GetMapping(value="/location", produces = APPLICATION_JSON_VALUE)
119 | @ApiOperation(value = "Retrieve location reading for a journey", response = List.class)
120 | @ApiResponse(code = 200, message = "Retrieve locartion reading for a journey")
121 | public ResponseEntity> getLocationReading(
122 | @ApiParam(name="spacecraftName", value="Spacecraft name",example = "gemini3",required=true )
123 | @PathVariable(value = "spacecraftName") String spacecraftName,
124 | @ApiParam(name="journeyId", value="Identifer for journey",example = "abb7c000-c310-11ac-8080-808080808080",required=true )
125 | @PathVariable(value = "journeyId") UUID journeyId,
126 | @ApiParam(name="pagesize", value="Requested page size, default is 10", required=false )
127 | @RequestParam("pagesize") Optional pageSize,
128 | @ApiParam(name="pagestate", value="Use to retrieve next pages", required=false )
129 | @RequestParam("pagestate") Optional pageState) {
130 | LOGGER.debug("Retrieving pressure readings for spacecraft {} and journey {}", spacecraftName, journeyId);
131 | return ResponseEntity.ok(astraService.getLocationReading(spacecraftName, journeyId, pageSize, pageState));
132 | }
133 |
134 | @PostMapping(value="/temperature", consumes = APPLICATION_JSON_VALUE)
135 | @ApiOperation(value = "Save temperature reading for a journey", response = List.class)
136 | @ApiResponse(code = 200, message = "Saved temperature reading for a journey")
137 | public ResponseEntity saveTemperatureReadings(
138 | @ApiParam(name="spacecraftName", value="Spacecraft name",example = "gemini3",required=true )
139 | @PathVariable(value = "spacecraftName") String spacecraftName,
140 | @ApiParam(name="journeyId", value="Identifier for journey",example = "abb7c000-c310-11ac-8080-808080808080",required=true )
141 | @PathVariable(value = "journeyId") UUID journeyId,
142 | @RequestBody SpacecraftTemperatureOverTime[] readings) {
143 | LOGGER.debug("Saving temperature readings for spacecraft {} and journey {}", spacecraftName, journeyId);
144 | if (null != readings && readings.length > 0) {
145 | astraService.insertTemperatureReading(readings);
146 | }
147 | return ResponseEntity.ok("OK");
148 | }
149 |
150 | @PostMapping(value="/location", consumes = APPLICATION_JSON_VALUE)
151 | @ApiOperation(value = "Save location reading for a journey", response = List.class)
152 | @ApiResponse(code = 200, message = "Saved location reading for a journey")
153 | public ResponseEntity saveLocationReadings(
154 | @ApiParam(name="spacecraftName", value="Spacecraft name",example = "gemini3",required=true )
155 | @PathVariable(value = "spacecraftName") String spacecraftName,
156 | @ApiParam(name="journeyId", value="Identifier for journey",example = "abb7c000-c310-11ac-8080-808080808080",required=true )
157 | @PathVariable(value = "journeyId") UUID journeyId,
158 | @RequestBody SpacecraftLocationOverTime[] readings) {
159 | LOGGER.debug("Saving location reading(s) for spacecraft {} and journey {}", spacecraftName, journeyId);
160 | if (null != readings && readings.length > 0) {
161 | astraService.insertLocationReading(readings);
162 | }
163 | return ResponseEntity.ok("OK");
164 | }
165 |
166 | @PostMapping(value="/pressure", consumes = APPLICATION_JSON_VALUE)
167 | @ApiOperation(value = "Save pressure reading for a journey", response = List.class)
168 | @ApiResponse(code = 200, message = "Saved pressure reading for a journey")
169 | public ResponseEntity savePressureReadings(
170 | @ApiParam(name="spacecraftName", value="Spacecraft name",example = "gemini3",required=true )
171 | @PathVariable(value = "spacecraftName") String spacecraftName,
172 | @ApiParam(name="journeyId", value="Identifier for journey",example = "abb7c000-c310-11ac-8080-808080808080",required=true )
173 | @PathVariable(value = "journeyId") UUID journeyId,
174 | @RequestBody SpacecraftPressureOverTime[] readings) {
175 | LOGGER.debug("Saving pressure readings for spacecraft {} and journey {}", spacecraftName, journeyId);
176 | if (null != readings && readings.length > 0) {
177 | astraService.insertPressureReading(readings);
178 | }
179 | return ResponseEntity.ok("OK");
180 | }
181 |
182 | @PostMapping(value="/speed", consumes = APPLICATION_JSON_VALUE)
183 | @ApiOperation(value = "Save speed reading for a journey", response = List.class)
184 | @ApiResponse(code = 200, message = "Saved speed reading for a journey")
185 | public ResponseEntity saveSpeedReadings(
186 | @ApiParam(name="spacecraftName", value="Spacecraft name",example = "gemini3",required=true )
187 | @PathVariable(value = "spacecraftName") String spacecraftName,
188 | @ApiParam(name="journeyId", value="Identifier for journey",example = "abb7c000-c310-11ac-8080-808080808080",required=true )
189 | @PathVariable(value = "journeyId") UUID journeyId,
190 | @RequestBody SpacecraftSpeedOverTime[] readings) {
191 | LOGGER.debug("Saving speed readings for spacecraft {} and journey {}", spacecraftName, journeyId);
192 | if (null != readings && readings.length > 0) {
193 | astraService.insertSpeedReading(readings);
194 | }
195 | return ResponseEntity.ok("OK");
196 | }
197 |
198 | }
199 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/controller/SpacecraftController.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.controller;
2 |
3 | import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
4 | import static org.springframework.http.MediaType.TEXT_PLAIN_VALUE;
5 | import static org.springframework.web.bind.annotation.RequestMethod.GET;
6 |
7 | import java.net.URI;
8 | import java.util.List;
9 | import java.util.Optional;
10 | import java.util.UUID;
11 |
12 | import javax.servlet.http.HttpServletRequest;
13 |
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 | import org.springframework.http.MediaType;
17 | import org.springframework.http.ResponseEntity;
18 | import org.springframework.web.bind.annotation.CrossOrigin;
19 | import org.springframework.web.bind.annotation.GetMapping;
20 | import org.springframework.web.bind.annotation.PathVariable;
21 | import org.springframework.web.bind.annotation.PostMapping;
22 | import org.springframework.web.bind.annotation.RequestBody;
23 | import org.springframework.web.bind.annotation.RequestMapping;
24 | import org.springframework.web.bind.annotation.RestController;
25 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
26 |
27 | import com.datastax.astra.entity.SpacecraftJourneyCatalog;
28 | import com.datastax.astra.service.AstraService;
29 |
30 | import io.swagger.annotations.Api;
31 | import io.swagger.annotations.ApiImplicitParam;
32 | import io.swagger.annotations.ApiImplicitParams;
33 | import io.swagger.annotations.ApiOperation;
34 | import io.swagger.annotations.ApiParam;
35 | import io.swagger.annotations.ApiResponse;
36 | import io.swagger.annotations.ApiResponses;
37 |
38 | /**
39 | * REST Controller for operations on spacecrafts catalog.O
40 | */
41 | @CrossOrigin
42 | @RestController
43 | @Api(
44 | value = "/api/spacecraft",
45 | description = "Operations on spacecrafts catalog")
46 | @RequestMapping("/api/spacecraft")
47 | public class SpacecraftController {
48 |
49 | /** Logger for the class. */
50 | private static final Logger LOGGER = LoggerFactory.getLogger(SpacecraftController.class);
51 |
52 | /** Service implementation Injection. */
53 | private AstraService astraService;
54 |
55 | /**
56 | * Constructor.
57 | *
58 | * @param spacecraftService
59 | * service implementation
60 | */
61 | public SpacecraftController(AstraService spacecraftService) {
62 | this.astraService = spacecraftService;
63 | }
64 |
65 | /**
66 | * List all spacecrafts from the catalog
67 | *
68 | * @return
69 | * list all {@link SpacecraftJourneyCatalog} available in the table
70 | */
71 | @GetMapping(produces = APPLICATION_JSON_VALUE)
72 | @ApiOperation(value = "List all spacecrafts and journeys", response = List.class)
73 | @ApiResponse(code = 200, message = "List all journeys for a spacecraft")
74 | public ResponseEntity> findAllSpacecrafts() {
75 | LOGGER.info("Retrieving all spacecrafts");
76 | return ResponseEntity.ok(astraService.findAllSpacecrafts());
77 | }
78 |
79 | /**
80 | * List all journeys for a dedicated spacecraft. If the spacecraft is not found we will show an empty list (an dnot 404.)
81 | *
82 | * @param spacecraft_name
83 | * spacecraft_name to locate journeys
84 | * @return
85 | * list of associated journey, can be empty
86 | */
87 | @GetMapping(value = "/{spacecraftName}", produces = APPLICATION_JSON_VALUE)
88 | @ApiOperation(value = "List all journeys for a dedicated spacecraft name", response = List.class)
89 | @ApiResponse(code = 200, message = "List all journeys for a dedicated spacecraft name")
90 | public ResponseEntity> findAllJourneysForSpacecraft(
91 | @ApiParam(name="spacecraftName", value="Spacecraft name",example = "gemini3",required=true )
92 | @PathVariable(value = "spacecraftName") String spaceCraftName) {
93 | LOGGER.info("Retrieving all journey for spacecraft {}", spaceCraftName);
94 | return ResponseEntity.ok(astraService.findAllJourneysForSpacecraft(spaceCraftName));
95 | }
96 |
97 | /**
98 | * Find a unique spacecraft journey from its reference.
99 | *
100 | * @param spacecraft_name
101 | * spacecraft_name to locate journeys
102 | * @return
103 | * list of associated journey, can be empty
104 | */
105 | @RequestMapping(
106 | value = "/{spacecraftName}/{journeyId}",
107 | method = GET,
108 | produces = APPLICATION_JSON_VALUE)
109 | @ApiOperation(value = "Retrieve a journey from its spacecraftname and journeyid", response = List.class)
110 | @ApiResponses({
111 | @ApiResponse(code = 200, message = "Returnings SpacecraftJourneyCatalog"),
112 | @ApiResponse(code = 400, message = "spacecraftName is blank or contains invalid characters (expecting AlphaNumeric)"),
113 | @ApiResponse(code = 404, message = "No journey exists for the provided spacecraftName and journeyid")
114 | })
115 | public ResponseEntity findSpacecraftJourney(
116 | @ApiParam(name="spacecraftName", value="Spacecraft name",example = "gemini3",required=true )
117 | @PathVariable(value = "spacecraftName") String spacecraftName,
118 | @ApiParam(name="journeyId", value="Identifer for journey",example = "abb7c000-c310-11ac-8080-808080808080",required=true )
119 | @PathVariable(value = "journeyId") UUID journeyId) {
120 | LOGGER.info("Fetching journey with spacecraft name {} and journeyid {}", spacecraftName, journeyId);
121 | // Invoking Service
122 | Optional journey = astraService.findJourneyById(spacecraftName, journeyId);
123 | // Routing Result
124 | if (!journey.isPresent()) {
125 | LOGGER.warn("Journey with spacecraft name {} and journeyid {} has not been found", spacecraftName, journeyId);
126 | return ResponseEntity.notFound().build();
127 | }
128 | return ResponseEntity.ok(journey.get());
129 | }
130 |
131 | /**
132 | * Create a new Journey for a Spacecraft
133 | */
134 | @PostMapping(value = "/{spacecraftName}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = TEXT_PLAIN_VALUE)
135 | @ApiOperation(value = " Create a new Journey for a Spacecraft", response = String.class)
136 | @ApiResponses({
137 | @ApiResponse(code = 201, message = "Journey has been created"),
138 | @ApiResponse(code = 400, message = "Invalid Spacecraft name provided")
139 | })
140 | @ApiImplicitParams({
141 | @ApiImplicitParam(
142 | name = "summary",
143 | value = "Body of the request is a string representing the summary",
144 | required = true, dataType = "string", paramType = "body", example = "Going to the Moon")
145 | })
146 | public ResponseEntity createSpacecraftJourney(
147 | HttpServletRequest request,
148 | @ApiParam(name="spacecraftName", value="Spacecraft name",example = "soyuztm-8",required=true )
149 | @PathVariable(value = "spacecraftName") String spacecraftName,
150 | @RequestBody String summary) {
151 | UUID journeyId = astraService.createSpacecraftJourney(spacecraftName, summary);
152 | // HTTP Created spec, return target resource in 'location' header
153 | URI location = ServletUriComponentsBuilder.fromRequestUri(request)
154 | .replacePath("/api/spacecrafts/{spacecraftName}/{journeyId}")
155 | .buildAndExpand(spacecraftName, journeyId)
156 | .toUri();
157 | // HTTP 201 with confirmation number
158 | return ResponseEntity.created(location).body(journeyId.toString());
159 | }
160 |
161 |
162 | }
163 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/dao/SessionManager.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.dao;
2 |
3 | import java.io.FileNotFoundException;
4 | import java.nio.file.Paths;
5 |
6 | import com.datastax.astra.utils.CqlFileUtils;
7 | import com.datastax.oss.driver.api.core.CqlSession;
8 |
9 | /**
10 | * {@link CqlSession} will be created for each call and drop after.
11 | */
12 | public class SessionManager {
13 |
14 | /** Singleton Pattern. */
15 | private static SessionManager _instance = null;
16 |
17 | /** Connectivity Attributes. */
18 | private String userName;
19 | private String password;
20 | private String keySpace;
21 | private String secureConnectionBundlePath;
22 |
23 | /** Status and working session. */
24 | private boolean initialized = false;
25 | private CqlSession cqlSession;
26 |
27 | public static final String QUERY_HEALTH_CHECK = "select data_center from system.local";
28 |
29 | /**
30 | * Utility Method to initialized parameters.
31 | *
32 | * @return
33 | * singletong of the session Manager
34 | */
35 | public static synchronized SessionManager getInstance() {
36 | if (null == _instance) {
37 | _instance = new SessionManager();
38 | }
39 | return _instance;
40 | }
41 |
42 | /**
43 | * Initialize parameters.
44 | *
45 | * @param userName
46 | * current username
47 | * @param password
48 | * current password
49 | * @param secureConnectionBundlePath
50 | * zip bundle path on disl
51 | * @param keyspace
52 | * current keyspace
53 | */
54 | public void saveCredentials(String userName, String password, String keyspace, String secureConnectionBundlePath) {
55 | this.userName = userName;
56 | this.password = password;
57 | this.keySpace = keyspace;
58 | this.secureConnectionBundlePath = secureConnectionBundlePath;
59 | this.initialized = true;
60 | }
61 |
62 | /**
63 | * Test with no persistence.
64 | *
65 | * @param user
66 | * sample user name
67 | * @param password
68 | * sample password
69 | * @param keyspace
70 | * sample keyspace
71 | * @param secureConnectionBundlePath
72 | * temp file
73 | */
74 | public void testCredentials(String user, String passwd, String keyspce, String secureConnectionBundlePath) {
75 | // Autocloseable temporary session
76 | try (CqlSession tmpSession = CqlSession.builder()
77 | .withCloudSecureConnectBundle(Paths.get(secureConnectionBundlePath))
78 | .withAuthCredentials(user, passwd)
79 | .withKeyspace(keyspce).build()) {
80 | tmpSession.execute(QUERY_HEALTH_CHECK);
81 | } catch(RuntimeException re) {
82 | throw new IllegalStateException(re);
83 | }
84 | }
85 |
86 | /**
87 | * Getter accessor for attribute 'cqlSession'.
88 | *
89 | * @return
90 | * current value of 'cqlSession'
91 | */
92 | public CqlSession connectToAstra() {
93 | if (!isInitialized()) {
94 | throw new IllegalStateException("Please initialize the connection parameters first with saveCredentials(...)");
95 | }
96 | if (null == cqlSession) {
97 | cqlSession = CqlSession.builder().withCloudSecureConnectBundle(Paths.get(getSecureConnectionBundlePath()))
98 | .withAuthCredentials(getUserName(),getPassword())
99 | .withKeyspace(getKeySpace())
100 | .build();
101 |
102 | // Once session has been initialized, creating schema
103 | createSchemaIfNeeded(cqlSession);
104 | }
105 | return cqlSession;
106 | }
107 |
108 | protected void createSchemaIfNeeded(CqlSession cqlSession) {
109 | try {
110 | CqlFileUtils.executeCQLFile(cqlSession, "schema.cql");
111 | } catch (FileNotFoundException e) {
112 | throw new IllegalStateException(e);
113 | }
114 | }
115 |
116 | /**
117 | * IfO simple command failing => invalid connection
118 | */
119 | public void checkConnection() {
120 | try {
121 | connectToAstra().execute(QUERY_HEALTH_CHECK);
122 | } catch(RuntimeException re) {
123 | throw new IllegalStateException(re);
124 | }
125 | }
126 |
127 | /**
128 | * Cleanup session
129 | */
130 | public void close() {
131 | if (isInitialized() && null != cqlSession) {
132 | cqlSession.close();
133 | }
134 | }
135 |
136 | /**
137 | * Getter accessor for attribute 'userName'.
138 | *
139 | * @return
140 | * current value of 'userName'
141 | */
142 | public String getUserName() {
143 | return userName;
144 | }
145 |
146 | /**
147 | * Getter accessor for attribute 'password'.
148 | *
149 | * @return
150 | * current value of 'password'
151 | */
152 | public String getPassword() {
153 | return password;
154 | }
155 |
156 | /**
157 | * Getter accessor for attribute 'secureConnectionBundlePath'.
158 | *
159 | * @return
160 | * current value of 'secureConnectionBundlePath'
161 | */
162 | public String getSecureConnectionBundlePath() {
163 | return secureConnectionBundlePath;
164 | }
165 |
166 | /**
167 | * Getter accessor for attribute 'keySpace'.
168 | *
169 | * @return
170 | * current value of 'keySpace'
171 | */
172 | public String getKeySpace() {
173 | return keySpace;
174 | }
175 |
176 | /**
177 | * Getter accessor for attribute 'initialized'.
178 | *
179 | * @return
180 | * current value of 'initialized'
181 | */
182 | public boolean isInitialized() {
183 | return initialized;
184 | }
185 |
186 | }
187 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/dao/SpacecraftInstrumentsDao.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.dao;
2 |
3 | import java.util.Optional;
4 | import java.util.UUID;
5 | import java.util.concurrent.CompletionStage;
6 | import java.util.function.Function;
7 |
8 | import com.datastax.astra.entity.SpacecraftLocationOverTime;
9 | import com.datastax.astra.entity.SpacecraftPressureOverTime;
10 | import com.datastax.astra.entity.SpacecraftSpeedOverTime;
11 | import com.datastax.astra.entity.SpacecraftTemperatureOverTime;
12 | import com.datastax.oss.driver.api.core.PagingIterable;
13 | import com.datastax.oss.driver.api.core.cql.BoundStatementBuilder;
14 | import com.datastax.oss.driver.api.mapper.annotations.Dao;
15 | import com.datastax.oss.driver.api.mapper.annotations.Insert;
16 | import com.datastax.oss.driver.api.mapper.annotations.QueryProvider;
17 | import com.datastax.oss.driver.api.mapper.annotations.Select;
18 |
19 | /**
20 | * Operation to work with instruments
21 | */
22 | @Dao
23 | public interface SpacecraftInstrumentsDao {
24 |
25 | /**
26 | * Search for temperature readings with MAPPER
27 | */
28 | @Select(customWhereClause = "spacecraft_name= :spacecraftName AND journey_id= :journeyId")
29 | PagingIterable getTemperatureReading(
30 | String spacecraftName, UUID JourneyId,
31 | Function setAttributes);
32 |
33 | /**
34 | * Search for temperature readings with QUERY PROVIDER
35 | */
36 | @QueryProvider(providerClass = SpacecraftInstrumentsQueryProvider.class,
37 | entityHelpers = { SpacecraftTemperatureOverTime.class, SpacecraftPressureOverTime.class,
38 | SpacecraftLocationOverTime.class, SpacecraftSpeedOverTime.class})
39 | PagingIterable getTemperatureReading(
40 | String spacecraftName, UUID JourneyId,
41 | Optional pageSize,
42 | Optional pagingState);
43 |
44 | /**
45 | * Upsert a temperature reading.
46 | *
47 | * @param reading
48 | * The temperature reading
49 | * @return
50 | * if statement was applied
51 | */
52 | @Insert
53 | boolean upsertTemperature(SpacecraftTemperatureOverTime reading);
54 |
55 | /**
56 | * Bulk inserts of temperature readings.
57 | *
58 | * @param reading
59 | * The temperature readings
60 | */
61 | @QueryProvider(providerClass = SpacecraftInstrumentsQueryProvider.class,
62 | entityHelpers = { SpacecraftTemperatureOverTime.class, SpacecraftPressureOverTime.class,
63 | SpacecraftLocationOverTime.class, SpacecraftSpeedOverTime.class})
64 | CompletionStage insertTemperatureReadingAsync(SpacecraftTemperatureOverTime[] readings);
65 |
66 | @QueryProvider(providerClass = SpacecraftInstrumentsQueryProvider.class,
67 | entityHelpers = { SpacecraftTemperatureOverTime.class, SpacecraftPressureOverTime.class,
68 | SpacecraftLocationOverTime.class, SpacecraftSpeedOverTime.class})
69 | CompletionStage insertLocationReadingAsync(SpacecraftLocationOverTime[] readings);
70 |
71 | @QueryProvider(providerClass = SpacecraftInstrumentsQueryProvider.class,
72 | entityHelpers = { SpacecraftTemperatureOverTime.class, SpacecraftPressureOverTime.class,
73 | SpacecraftLocationOverTime.class, SpacecraftSpeedOverTime.class})
74 | CompletionStage insertPressureReadingAsync(SpacecraftPressureOverTime[] readings);
75 |
76 | @QueryProvider(providerClass = SpacecraftInstrumentsQueryProvider.class,
77 | entityHelpers = { SpacecraftTemperatureOverTime.class, SpacecraftPressureOverTime.class,
78 | SpacecraftLocationOverTime.class, SpacecraftSpeedOverTime.class})
79 | CompletionStage insertSpeedReadingAsync(SpacecraftSpeedOverTime[] readings);
80 |
81 |
82 |
83 |
84 | /**
85 | * Upsert a location reading.
86 | *
87 | * @param reading
88 | * The location reading
89 | * @return
90 | * if statement was applied
91 | */
92 | @Insert
93 | boolean upsertLocation(SpacecraftLocationOverTime reading);
94 |
95 | /**
96 | * Upsert a pressure reading.
97 | *
98 | * @param reading
99 | * The pressure reading
100 | * @return
101 | * if statement was applied
102 | */
103 | @Insert
104 | boolean upsertPressure(SpacecraftPressureOverTime reading);
105 |
106 | /**
107 | * Upsert a speed reading.
108 | *
109 | * @param reading
110 | * The speed reading
111 | * @return
112 | * if statement was applied
113 | */
114 | @Insert
115 | boolean upsertSpeed(SpacecraftSpeedOverTime reading);
116 |
117 | /**
118 | * Search for pressure readings.
119 | */
120 | @QueryProvider(providerClass = SpacecraftInstrumentsQueryProvider.class,
121 | entityHelpers = { SpacecraftTemperatureOverTime.class, SpacecraftPressureOverTime.class,
122 | SpacecraftLocationOverTime.class, SpacecraftSpeedOverTime.class})
123 | PagingIterable getPressureReading(
124 | String spacecraftName, UUID JourneyId, Optional pageSize, Optional pagingState);
125 |
126 | /**
127 | * Search for speed readings.
128 | */
129 | @QueryProvider(providerClass = SpacecraftInstrumentsQueryProvider.class,
130 | entityHelpers = { SpacecraftTemperatureOverTime.class, SpacecraftPressureOverTime.class,
131 | SpacecraftLocationOverTime.class, SpacecraftSpeedOverTime.class})
132 | PagingIterable getSpeedReading(
133 | String spacecraftName, UUID JourneyId, Optional pageSize, Optional spagingState);
134 |
135 | /**
136 | * Search for location readings.
137 | */
138 | @QueryProvider(providerClass = SpacecraftInstrumentsQueryProvider.class,
139 | entityHelpers = { SpacecraftTemperatureOverTime.class, SpacecraftPressureOverTime.class,
140 | SpacecraftLocationOverTime.class, SpacecraftSpeedOverTime.class})
141 | PagingIterable getLocationReading(
142 | String spacecraftName, UUID JourneyId, Optional pageSize, Optional pagingState);
143 |
144 | /**
145 | * Insert instruments.
146 | */
147 | @QueryProvider(providerClass = SpacecraftInstrumentsQueryProvider.class,
148 | entityHelpers = { SpacecraftTemperatureOverTime.class, SpacecraftPressureOverTime.class,
149 | SpacecraftLocationOverTime.class, SpacecraftSpeedOverTime.class})
150 | void insertInstruments(
151 | SpacecraftTemperatureOverTime temperature, SpacecraftPressureOverTime pressure,
152 | SpacecraftSpeedOverTime speed, SpacecraftLocationOverTime location);
153 | }
154 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/dao/SpacecraftInstrumentsQueryProvider.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.dao;
2 |
3 | import static com.datastax.astra.entity.AbstractInstrumentReading.COLUMN_JOURNEY_ID;
4 | import static com.datastax.astra.entity.AbstractInstrumentReading.COLUMN_SPACECRAFT_NAME;
5 | import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.bindMarker;
6 | import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.selectFrom;
7 | import static com.datastax.oss.driver.api.querybuilder.relation.Relation.column;
8 |
9 | import java.util.Arrays;
10 | import java.util.Optional;
11 | import java.util.UUID;
12 | import java.util.concurrent.CompletionStage;
13 |
14 | import com.datastax.astra.entity.SpacecraftLocationOverTime;
15 | import com.datastax.astra.entity.SpacecraftPressureOverTime;
16 | import com.datastax.astra.entity.SpacecraftSpeedOverTime;
17 | import com.datastax.astra.entity.SpacecraftTemperatureOverTime;
18 | import com.datastax.oss.driver.api.core.CqlSession;
19 | import com.datastax.oss.driver.api.core.PagingIterable;
20 | import com.datastax.oss.driver.api.core.cql.BatchStatement;
21 | import com.datastax.oss.driver.api.core.cql.BatchStatementBuilder;
22 | import com.datastax.oss.driver.api.core.cql.BoundStatement;
23 | import com.datastax.oss.driver.api.core.cql.BoundStatementBuilder;
24 | import com.datastax.oss.driver.api.core.cql.DefaultBatchType;
25 | import com.datastax.oss.driver.api.core.cql.PreparedStatement;
26 | import com.datastax.oss.driver.api.core.cql.ResultSet;
27 | import com.datastax.oss.driver.api.mapper.MapperContext;
28 | import com.datastax.oss.driver.api.mapper.annotations.QueryProvider;
29 | import com.datastax.oss.driver.api.mapper.entity.EntityHelper;
30 | import com.datastax.oss.driver.api.mapper.entity.saving.NullSavingStrategy;
31 | import com.datastax.oss.protocol.internal.util.Bytes;
32 |
33 | /**
34 | * Implementation of Dynamic queries.
35 | *
36 | */
37 | public class SpacecraftInstrumentsQueryProvider {
38 |
39 | private CqlSession cqlSession;
40 |
41 | /** Helper for bean, tables mappings. */
42 | private EntityHelper ehTemperature;
43 | private EntityHelper ehPressure;
44 | private EntityHelper ehLocation;
45 | private EntityHelper ehSpeed;
46 |
47 | /** Statements Against Astra. */
48 | private PreparedStatement psInsertTemperatureReading;
49 | private PreparedStatement psInsertPressureReading;
50 | private PreparedStatement psInsertLocationReading;
51 | private PreparedStatement psInsertSpeedReading;
52 |
53 | private PreparedStatement psSelectTemperatureReading;
54 | private PreparedStatement psSelectPressureReading;
55 | private PreparedStatement psSelectLocationReading;
56 | private PreparedStatement psSelectSpeedReading;
57 |
58 | /**
59 | * Constructor invoked by the DataStax driver based on Annotation {@link QueryProvider}
60 | * set on class {@link SpacecraftInstrumentsDao}.
61 | *
62 | * @param context
63 | * context to extrat dse session
64 | * @param ehTemperature
65 | * entity helper to interact with bean {@link SpacecraftTemperatureOverTime}
66 | * @param ehPressure
67 | * entity helper to interact with bean {@link SpacecraftPressureOverTime}
68 | * @param ehLocation
69 | * entity helper to interact with bean {@link SpacecraftLocationOverTime}
70 | */
71 | public SpacecraftInstrumentsQueryProvider(MapperContext context,
72 | EntityHelper ehTemperature,
73 | EntityHelper ehPressure,
74 | EntityHelper ehLocation,
75 | EntityHelper ehSpeed) {
76 | this.cqlSession = context.getSession();
77 | this.ehTemperature = ehTemperature;
78 | this.ehPressure = ehPressure;
79 | this.ehSpeed = ehSpeed;
80 | this.ehLocation = ehLocation;
81 |
82 | // Leveraging EntityHelper for insert queries
83 | psInsertTemperatureReading = cqlSession.prepare(ehTemperature.insert().asCql());
84 | psInsertPressureReading = cqlSession.prepare(ehPressure.insert().asCql());
85 | psInsertLocationReading = cqlSession.prepare(ehLocation.insert().asCql());
86 | psInsertSpeedReading = cqlSession.prepare(ehSpeed.insert().asCql());
87 |
88 | psSelectTemperatureReading = cqlSession.prepare(
89 | selectFrom(SpacecraftTemperatureOverTime.TABLE_NAME).all()
90 | .where(column(COLUMN_SPACECRAFT_NAME).isEqualTo(bindMarker(COLUMN_SPACECRAFT_NAME)))
91 | .where(column(COLUMN_JOURNEY_ID).isEqualTo(bindMarker(COLUMN_JOURNEY_ID)))
92 | .build());
93 | psSelectPressureReading = cqlSession.prepare(
94 | selectFrom(SpacecraftPressureOverTime.TABLE_NAME).all()
95 | .where(column(COLUMN_SPACECRAFT_NAME).isEqualTo(bindMarker(COLUMN_SPACECRAFT_NAME)))
96 | .where(column(COLUMN_JOURNEY_ID).isEqualTo(bindMarker(COLUMN_JOURNEY_ID)))
97 | .build());
98 | psSelectSpeedReading = cqlSession.prepare(
99 | selectFrom(SpacecraftSpeedOverTime.TABLE_NAME).all()
100 | .where(column(COLUMN_SPACECRAFT_NAME).isEqualTo(bindMarker(COLUMN_SPACECRAFT_NAME)))
101 | .where(column(COLUMN_JOURNEY_ID).isEqualTo(bindMarker(COLUMN_JOURNEY_ID)))
102 | .build());
103 | psSelectLocationReading = cqlSession.prepare(
104 | selectFrom(SpacecraftLocationOverTime.TABLE_NAME).all()
105 | .where(column(COLUMN_SPACECRAFT_NAME).isEqualTo(bindMarker(COLUMN_SPACECRAFT_NAME)))
106 | .where(column(COLUMN_JOURNEY_ID).isEqualTo(bindMarker(COLUMN_JOURNEY_ID)))
107 | .build());
108 | }
109 |
110 | /**
111 | * Insert instruments values for a timestamp.
112 | */
113 | public void insertInstruments(
114 | SpacecraftTemperatureOverTime temperature, SpacecraftPressureOverTime pressure,
115 | SpacecraftSpeedOverTime speed, SpacecraftLocationOverTime location) {
116 | cqlSession.executeAsync(BatchStatement.builder(DefaultBatchType.LOGGED)
117 | .addStatement(bind(psInsertTemperatureReading, temperature, ehTemperature))
118 | .addStatement(bind(psInsertPressureReading, pressure, ehPressure))
119 | .addStatement(bind(psInsertSpeedReading, speed, ehSpeed))
120 | .addStatement(bind(psInsertLocationReading, location, ehLocation))
121 | .build()).thenApply(rs -> null);
122 | }
123 |
124 | public CompletionStage insertLocationReadingAsync(SpacecraftLocationOverTime[] readings) {
125 | BatchStatementBuilder myBatch = BatchStatement.builder(DefaultBatchType.LOGGED);
126 | Arrays.stream(readings).forEach(read -> myBatch.addStatement(bind(psInsertLocationReading, read, ehLocation)));
127 | return cqlSession.executeAsync(myBatch.build()).thenApply(rs -> rs.wasApplied());
128 | }
129 |
130 | public CompletionStage insertTemperatureReadingAsync(SpacecraftTemperatureOverTime[] readings) {
131 | BatchStatementBuilder myBatch = BatchStatement.builder(DefaultBatchType.LOGGED);
132 | Arrays.stream(readings).forEach(read -> myBatch.addStatement(bind(psInsertTemperatureReading, read, ehTemperature)));
133 | return cqlSession.executeAsync(myBatch.build()).thenApply(rs -> rs.wasApplied());
134 | }
135 |
136 | public CompletionStage insertPressureReadingAsync(SpacecraftPressureOverTime[] readings) {
137 | BatchStatementBuilder myBatch = BatchStatement.builder(DefaultBatchType.LOGGED);
138 | Arrays.stream(readings).forEach(read -> myBatch.addStatement(bind(psInsertPressureReading, read, ehPressure)));
139 | return cqlSession.executeAsync(myBatch.build()).thenApply(rs -> rs.wasApplied());
140 | }
141 |
142 | public CompletionStage insertSpeedReadingAsync(SpacecraftSpeedOverTime[] readings) {
143 | BatchStatementBuilder myBatch = BatchStatement.builder(DefaultBatchType.LOGGED);
144 | Arrays.stream(readings).forEach(read -> myBatch.addStatement(bind(psInsertSpeedReading, read, ehSpeed)));
145 | return cqlSession.executeAsync(myBatch.build()).thenApplyAsync(rs -> rs.wasApplied());
146 | }
147 |
148 | /**
149 | * Retrieve Temperature reading for a journey.
150 | */
151 | public PagingIterable getTemperatureReading(
152 | String spacecraftName,
153 | UUID journeyId,
154 | Optional pageSize,
155 | Optional pagingState) {
156 |
157 | // Detailing operations for the first (next will be much compact)
158 |
159 | // (1) - Bind the prepared statement with parameters
160 | BoundStatement bsTemperature = psSelectTemperatureReading.bind()
161 | .setUuid(COLUMN_JOURNEY_ID, journeyId)
162 | .setString(COLUMN_SPACECRAFT_NAME, spacecraftName);
163 |
164 | // (2) - Update the bound statement to add paging metadata (pageSize, pageState)
165 | bsTemperature = paging(bsTemperature, pageSize, pagingState);
166 |
167 | // (3) - Executing query
168 | ResultSet resultSet = cqlSession.execute(bsTemperature);
169 |
170 | // (4) - Using the entity Help to marshall to expect bean
171 | return resultSet.map(ehTemperature::get);
172 | }
173 |
174 | /**
175 | * Retrieve Pressure reading for a journey.
176 | */
177 | public PagingIterable getPressureReading(
178 | String spacecraftName, UUID journeyId, Optional pageSize, Optional pagingState) {
179 | return cqlSession.execute(paging(psSelectPressureReading.bind()
180 | .setUuid(COLUMN_JOURNEY_ID, journeyId)
181 | .setString(COLUMN_SPACECRAFT_NAME, spacecraftName), pageSize, pagingState))
182 | .map(ehPressure::get);
183 | }
184 |
185 | /**
186 | * Retrieve Location reading for a journey.
187 | */
188 | public PagingIterable getLocationReading(
189 | String spacecraftName, UUID journeyId, Optional pageSize, Optional pagingState) {
190 | return cqlSession.execute(paging(psSelectLocationReading.bind()
191 | .setUuid(COLUMN_JOURNEY_ID, journeyId)
192 | .setString(COLUMN_SPACECRAFT_NAME, spacecraftName), pageSize, pagingState))
193 | .map(ehLocation::get);
194 | }
195 |
196 | /**
197 | * Retrieve Pressure reading for a journey.
198 | */
199 | public PagingIterable getSpeedReading(
200 | String spacecraftName, UUID journeyId, Optional pageSize, Optional pagingState) {
201 | return cqlSession.execute(paging(psSelectSpeedReading.bind()
202 | .setUuid(COLUMN_JOURNEY_ID, journeyId)
203 | .setString(COLUMN_SPACECRAFT_NAME, spacecraftName), pageSize, pagingState))
204 | .map(ehSpeed::get);
205 | }
206 |
207 | /**
208 | * Syntaxic sugar to help with paging
209 | */
210 | private BoundStatement paging(BoundStatement bs, Optional pageSize, Optional pagingState) {
211 | if(pageSize.isPresent()) {
212 | bs = bs.setPageSize(pageSize.get());
213 | }
214 | if (pagingState.isPresent()) {
215 | bs = bs.setPagingState(Bytes.fromHexString(pagingState.get()));
216 | };
217 | return bs;
218 | }
219 |
220 | /**
221 | * Syntaxic sugar to help with mapping
222 | */
223 | public static BoundStatement bind(PreparedStatement preparedStatement, T entity, EntityHelper entityHelper) {
224 | BoundStatementBuilder boundStatement = preparedStatement.boundStatementBuilder();
225 | entityHelper.set(entity, boundStatement, NullSavingStrategy.DO_NOT_SET);
226 | return boundStatement.build();
227 | }
228 | }
229 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/dao/SpacecraftJourneyDao.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.dao;
2 |
3 | import java.util.Optional;
4 | import java.util.UUID;
5 |
6 | import com.datastax.astra.entity.SpacecraftJourneyCatalog;
7 | import com.datastax.oss.driver.api.core.PagingIterable;
8 | import com.datastax.oss.driver.api.mapper.annotations.Dao;
9 | import com.datastax.oss.driver.api.mapper.annotations.Insert;
10 | import com.datastax.oss.driver.api.mapper.annotations.Query;
11 | import com.datastax.oss.driver.api.mapper.annotations.Select;
12 |
13 | /**
14 | * Defining Dao for Spacecraft requests.
15 | */
16 | @Dao
17 | public interface SpacecraftJourneyDao {
18 |
19 | /**
20 | * Find All spacecraft in the table.
21 | */
22 | @Query("SELECT * FROM ${keyspaceId}.${tableId}")
23 | PagingIterable findAll();
24 |
25 | /**
26 | * Find all journeys for a spacecraft name.
27 | *
28 | * @param spacecraftName
29 | * spacecraftname (Partition key)
30 | * @return
31 | * list of journeys
32 | */
33 | @Select(customWhereClause = SpacecraftJourneyCatalog.COLUMN_SPACECRAFT_NAME + "= :spacecraftName")
34 | PagingIterable findAllJourneysForSpacecraft(String spacecraftName);
35 |
36 | /**
37 | * Find a journey from its id and a spacecraft name (PK)
38 | *
39 | * @param spacecraftName
40 | * spacecraft name
41 | * @param journeyId
42 | * journey unique identifier
43 | * @return
44 | * journey details if it exists or empty
45 | */
46 | @Select
47 | Optional findById(String spacecraftName, UUID journeyId);
48 |
49 | /**
50 | * Upsert a new journey.
51 | *
52 | * @param spacecraftJourney
53 | * bean representing a journey
54 | * @return
55 | * if statement was applied
56 | */
57 | @Insert
58 | boolean upsert(SpacecraftJourneyCatalog spacecraftJourney);
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/dao/SpacecraftMapper.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.dao;
2 |
3 | import com.datastax.oss.driver.api.core.CqlIdentifier;
4 | import com.datastax.oss.driver.api.mapper.annotations.Dao;
5 | import com.datastax.oss.driver.api.mapper.annotations.DaoFactory;
6 | import com.datastax.oss.driver.api.mapper.annotations.DaoKeyspace;
7 | import com.datastax.oss.driver.api.mapper.annotations.Mapper;
8 |
9 | /**
10 | * Wrapper for all {@link Dao} generated by DataStax Driver.
11 | */
12 | @Mapper
13 | public interface SpacecraftMapper {
14 |
15 | /**
16 | * Initialization of Dao {@link RatingDseDao}
17 | *
18 | * @param keyspace
19 | * working keyspace name
20 | * @return
21 | * instanciation with the mappers
22 | */
23 | @DaoFactory
24 | SpacecraftJourneyDao spacecraftJourneyDao(@DaoKeyspace CqlIdentifier keyspace);
25 |
26 | @DaoFactory
27 | SpacecraftInstrumentsDao spacecraftInstrumentsDao(@DaoKeyspace CqlIdentifier keyspace);
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/doc/DocumentationApiConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.doc;
2 |
3 | /*
4 | * #%L
5 | * ff4j-spring-boot-web-api
6 | * %%
7 | * Copyright (C) 2013 - 2016 FF4J
8 | * %%
9 | * Licensed under the Apache License, Version 2.0 (the "License");
10 | * you may not use this file except in compliance with the License.
11 | * You may obtain a copy of the License at
12 | *
13 | * http://www.apache.org/licenses/LICENSE-2.0
14 | *
15 | * Unless required by applicable law or agreed to in writing, software
16 | * distributed under the License is distributed on an "AS IS" BASIS,
17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | * See the License for the specific language governing permissions and
19 | * limitations under the License.
20 | * #L%
21 | */
22 |
23 | import org.springframework.context.annotation.Bean;
24 | import org.springframework.context.annotation.Configuration;
25 |
26 | import com.datastax.astra.GettingStartedWithAstra;
27 |
28 | import springfox.documentation.builders.ApiInfoBuilder;
29 | import springfox.documentation.builders.PathSelectors;
30 | import springfox.documentation.builders.RequestHandlerSelectors;
31 | import springfox.documentation.service.ApiInfo;
32 | import springfox.documentation.spi.DocumentationType;
33 | import springfox.documentation.spring.web.plugins.Docket;
34 | import springfox.documentation.swagger2.annotations.EnableSwagger2;
35 |
36 | /**
37 | * Documentation of the API
38 | *
39 | * @author DataStax Evangelist Team
40 | */
41 | @Configuration
42 | @EnableSwagger2
43 | public class DocumentationApiConfiguration {
44 |
45 | @Bean
46 | public Docket api() {
47 | return new Docket(DocumentationType.SWAGGER_2)
48 | .groupName("GettingStartedWithAstra")
49 | .select()
50 | .apis(RequestHandlerSelectors.basePackage("com.datastax.astra"))
51 | .paths(PathSelectors.regex("/api.*"))
52 | .build()
53 | .apiInfo(apiInfo())
54 | .useDefaultResponseMessages(false);
55 | }
56 |
57 | /**
58 | * Initialization of documentation
59 | *
60 | * @return static infos
61 | */
62 | private ApiInfo apiInfo() {
63 | ApiInfoBuilder builder = new ApiInfoBuilder();
64 | builder.title("Astra Getting Started Backend API");
65 | builder.description("Start with Astra in Minute");
66 | builder.version(GettingStartedWithAstra.class.getPackage().getImplementationVersion());
67 | return builder.build();
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/doc/DocumentationController.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.doc;
2 |
3 | import org.springframework.web.bind.annotation.RequestMapping;
4 | import org.springframework.web.bind.annotation.RequestMethod;
5 | import org.springframework.web.bind.annotation.RestController;
6 |
7 | /**
8 | * We redirect to the API documentation page
9 | */
10 | @RestController
11 | @RequestMapping("/")
12 | public class DocumentationController {
13 |
14 | @RequestMapping(value = "/", method = RequestMethod.GET, produces = "text/html")
15 | public String redirectToDoc() {
16 | return new StringBuilder(""
17 | + ""
18 | + " "
19 | + " "
20 | + " "
21 | + " ").toString();
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/entity/AbstractInstrumentReading.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.entity;
2 |
3 | import java.time.Instant;
4 | import java.util.UUID;
5 |
6 | import com.datastax.oss.driver.api.mapper.annotations.ClusteringColumn;
7 | import com.datastax.oss.driver.api.mapper.annotations.CqlName;
8 | import com.datastax.oss.driver.api.mapper.annotations.PartitionKey;
9 |
10 | /**
11 | * Mutualized fields for all readings.
12 | */
13 | public abstract class AbstractInstrumentReading {
14 |
15 | /** Column Names. */
16 | public static final String COLUMN_SPACECRAFT_NAME = "spacecraft_name";
17 | public static final String COLUMN_JOURNEY_ID = "journey_id";
18 | public static final String COLUMN_READING_TIME = "reading_time";
19 |
20 | @PartitionKey(0)
21 | @CqlName(COLUMN_SPACECRAFT_NAME)
22 | private String spacecraft_name;
23 |
24 | @PartitionKey(1)
25 | @CqlName(COLUMN_JOURNEY_ID)
26 | private UUID journey_id;
27 |
28 | @ClusteringColumn
29 | @CqlName(COLUMN_READING_TIME)
30 | private Instant reading_time;
31 |
32 | /**
33 | * Getter accessor for attribute 'spacecraft_name'.
34 | *
35 | * @return
36 | * current value of 'spacecraft_name'
37 | */
38 | public String getSpacecraft_name() {
39 | return spacecraft_name;
40 | }
41 |
42 | /**
43 | * Setter accessor for attribute 'spacecraft_name'.
44 | * @param spacecraft_name
45 | * new value for 'spacecraft_name '
46 | */
47 | public void setSpacecraft_name(String spacecraft_name) {
48 | this.spacecraft_name = spacecraft_name;
49 | }
50 |
51 | /**
52 | * Getter accessor for attribute 'journey_id'.
53 | *
54 | * @return
55 | * current value of 'journey_id'
56 | */
57 | public UUID getJourney_id() {
58 | return journey_id;
59 | }
60 |
61 | /**
62 | * Setter accessor for attribute 'journey_id'.
63 | * @param journey_id
64 | * new value for 'journey_id '
65 | */
66 | public void setJourney_id(UUID journey_id) {
67 | this.journey_id = journey_id;
68 | }
69 |
70 | /**
71 | * Getter accessor for attribute 'reading_time'.
72 | *
73 | * @return
74 | * current value of 'reading_time'
75 | */
76 | public Instant getReading_time() {
77 | return reading_time;
78 | }
79 |
80 | /**
81 | * Setter accessor for attribute 'reading_time'.
82 | * @param reading_time
83 | * new value for 'reading_time '
84 | */
85 | public void setReading_time(Instant reading_time) {
86 | this.reading_time = reading_time;
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/entity/LocationUdt.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.entity;
2 |
3 | import com.datastax.oss.driver.api.mapper.annotations.CqlName;
4 | import com.datastax.oss.driver.api.mapper.annotations.Entity;
5 |
6 | /**
7 | * Bean for Location UDT.s
8 | */
9 | @Entity
10 | @CqlName(LocationUdt.UDT_TYPE_NAME)
11 | public class LocationUdt {
12 |
13 | /** Constants for UDT. */
14 | public static final String UDT_TYPE_NAME = "location";
15 | public static final String XCOORDINATE = "x_coordinate";
16 | public static final String YCOORDINATE = "y_coordinate";
17 | public static final String ZCOORDINATE = "z_coordinate";
18 |
19 | @CqlName(XCOORDINATE)
20 | private double x_coordinate;
21 |
22 | @CqlName(YCOORDINATE)
23 | private double y_coordinate;
24 |
25 | @CqlName(ZCOORDINATE)
26 | private double z_coordinate;
27 |
28 | /**
29 | * Default constructor.
30 | */
31 | public LocationUdt() {}
32 |
33 | /**
34 | * Init location with coordinates.
35 | */
36 | public LocationUdt(double x, double y, double z) {
37 | this.x_coordinate = x;
38 | this.y_coordinate = y;
39 | this.z_coordinate = z;
40 | }
41 |
42 | /**
43 | * Getter accessor for attribute 'x_coordinate'.
44 | *
45 | * @return
46 | * current value of 'x_coordinate'
47 | */
48 | public double getX_coordinate() {
49 | return x_coordinate;
50 | }
51 |
52 | /**
53 | * Setter accessor for attribute 'x_coordinate'.
54 | * @param x_coordinate
55 | * new value for 'x_coordinate '
56 | */
57 | public void setX_coordinate(double x_coordinate) {
58 | this.x_coordinate = x_coordinate;
59 | }
60 |
61 | /**
62 | * Getter accessor for attribute 'y_coordinate'.
63 | *
64 | * @return
65 | * current value of 'y_coordinate'
66 | */
67 | public double getY_coordinate() {
68 | return y_coordinate;
69 | }
70 |
71 | /**
72 | * Setter accessor for attribute 'y_coordinate'.
73 | * @param y_coordinate
74 | * new value for 'y_coordinate '
75 | */
76 | public void setY_coordinate(double y_coordinate) {
77 | this.y_coordinate = y_coordinate;
78 | }
79 |
80 | /**
81 | * Getter accessor for attribute 'z_coordinate'.
82 | *
83 | * @return
84 | * current value of 'z_coordinate'
85 | */
86 | public double getZ_coordinate() {
87 | return z_coordinate;
88 | }
89 |
90 | /**
91 | * Setter accessor for attribute 'z_coordinate'.
92 | * @param z_coordinate
93 | * new value for 'z_coordinate '
94 | */
95 | public void setZ_coordinate(double z_coordinate) {
96 | this.z_coordinate = z_coordinate;
97 | }
98 |
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/entity/SpacecraftJourneyCatalog.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.entity;
2 |
3 | import java.io.Serializable;
4 | import java.time.Instant;
5 | import java.util.UUID;
6 |
7 | import com.datastax.oss.driver.api.core.CqlIdentifier;
8 | import com.datastax.oss.driver.api.core.CqlSession;
9 | import com.datastax.oss.driver.api.core.metadata.schema.ClusteringOrder;
10 | import com.datastax.oss.driver.api.core.type.DataTypes;
11 | import com.datastax.oss.driver.api.mapper.annotations.ClusteringColumn;
12 | import com.datastax.oss.driver.api.mapper.annotations.CqlName;
13 | import com.datastax.oss.driver.api.mapper.annotations.Entity;
14 | import com.datastax.oss.driver.api.mapper.annotations.PartitionKey;
15 | import com.datastax.oss.driver.api.querybuilder.SchemaBuilder;
16 | import com.fasterxml.jackson.annotation.JsonProperty;
17 |
18 |
19 | /**
20 | * Entity representing Table
21 | */
22 | @Entity
23 | @CqlName(SpacecraftJourneyCatalog.TABLE_NAME)
24 | public class SpacecraftJourneyCatalog implements Serializable {
25 |
26 | /** Serial. */
27 | private static final long serialVersionUID = 1L;
28 |
29 | /** Constants.*/
30 | public static final String TABLE_NAME = "spacecraft_journey_catalog";
31 | public static final String COLUMN_SPACECRAFT_NAME = "spacecraft_name";
32 | public static final String COLUMN_ID = "journey_id";
33 | public static final String COLUMN_START = "start";
34 | public static final String COLUMN_END = "end";
35 | public static final String COLUMN_ACTIVE = "active";
36 | public static final String COLUMN_SUMMARY = "summary";
37 |
38 | @PartitionKey
39 | @CqlName(COLUMN_SPACECRAFT_NAME)
40 | @JsonProperty(COLUMN_SPACECRAFT_NAME)
41 | private String name;
42 |
43 | @ClusteringColumn
44 | @CqlName(COLUMN_ID)
45 | @JsonProperty(COLUMN_ID)
46 | private UUID journeyId;
47 |
48 | @CqlName(COLUMN_START)
49 | private Instant start;
50 |
51 | @CqlName(COLUMN_END)
52 | private Instant end;
53 |
54 | @CqlName(COLUMN_ACTIVE)
55 | private Boolean active;
56 |
57 | @CqlName(COLUMN_SUMMARY)
58 | private String summary;
59 |
60 | public SpacecraftJourneyCatalog() {}
61 |
62 | /**
63 | * Create table if not exist.
64 | *
65 | * @param session
66 | * current cql session
67 | */
68 | public static void createTable(CqlSession session) {
69 | session.execute(SchemaBuilder
70 | .createTable(CqlIdentifier.fromCql(TABLE_NAME))
71 | .ifNotExists()
72 | .withPartitionKey(COLUMN_SPACECRAFT_NAME, DataTypes.TEXT)
73 | .withClusteringColumn(COLUMN_ID, DataTypes.TIMEUUID)
74 | .withColumn(COLUMN_START, DataTypes.TIMESTAMP)
75 | .withColumn(COLUMN_END, DataTypes.TIMESTAMP)
76 | .withColumn(COLUMN_ACTIVE, DataTypes.BOOLEAN)
77 | .withColumn(COLUMN_SUMMARY, DataTypes.TEXT)
78 | .withClusteringOrder(COLUMN_ID, ClusteringOrder.DESC)
79 | .build());
80 | }
81 |
82 | /**
83 | * Getter accessor for attribute 'name'.
84 | *
85 | * @return
86 | * current value of 'name'
87 | */
88 | public String getName() {
89 | return name;
90 | }
91 |
92 | /**
93 | * Setter accessor for attribute 'name'.
94 | * @param name
95 | * new value for 'name '
96 | */
97 | public void setName(String name) {
98 | this.name = name;
99 | }
100 |
101 | /**
102 | * Getter accessor for attribute 'journeyId'.
103 | *
104 | * @return
105 | * current value of 'journeyId'
106 | */
107 | public UUID getJourneyId() {
108 | return journeyId;
109 | }
110 |
111 | /**
112 | * Setter accessor for attribute 'journeyId'.
113 | * @param journeyId
114 | * new value for 'journeyId '
115 | */
116 | public void setJourneyId(UUID journeyId) {
117 | this.journeyId = journeyId;
118 | }
119 |
120 | /**
121 | * Getter accessor for attribute 'start'.
122 | *
123 | * @return
124 | * current value of 'start'
125 | */
126 | public Instant getStart() {
127 | return start;
128 | }
129 |
130 | /**
131 | * Setter accessor for attribute 'start'.
132 | * @param start
133 | * new value for 'start '
134 | */
135 | public void setStart(Instant start) {
136 | this.start = start;
137 | }
138 |
139 | /**
140 | * Getter accessor for attribute 'end'.
141 | *
142 | * @return
143 | * current value of 'end'
144 | */
145 | public Instant getEnd() {
146 | return end;
147 | }
148 |
149 | /**
150 | * Setter accessor for attribute 'end'.
151 | * @param end
152 | * new value for 'end '
153 | */
154 | public void setEnd(Instant end) {
155 | this.end = end;
156 | }
157 |
158 | /**
159 | * Getter accessor for attribute 'active'.
160 | *
161 | * @return
162 | * current value of 'active'
163 | */
164 | public Boolean getActive() {
165 | return active;
166 | }
167 |
168 | /**
169 | * Setter accessor for attribute 'active'.
170 | * @param active
171 | * new value for 'active '
172 | */
173 | public void setActive(Boolean active) {
174 | this.active = active;
175 | }
176 |
177 | /**
178 | * Getter accessor for attribute 'summary'.
179 | *
180 | * @return
181 | * current value of 'summary'
182 | */
183 | public String getSummary() {
184 | return summary;
185 | }
186 |
187 | /**
188 | * Setter accessor for attribute 'summary'.
189 | * @param summary
190 | * new value for 'summary '
191 | */
192 | public void setSummary(String summary) {
193 | this.summary = summary;
194 | }
195 |
196 |
197 | }
198 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/entity/SpacecraftLocationOverTime.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.entity;
2 |
3 | import com.datastax.oss.driver.api.mapper.annotations.CqlName;
4 | import com.datastax.oss.driver.api.mapper.annotations.Entity;
5 |
6 | /**
7 | * Bean Mapping table spacecraft_temperature_over_time.
8 | */
9 | @Entity
10 | @CqlName(SpacecraftLocationOverTime.TABLE_NAME)
11 | public class SpacecraftLocationOverTime extends AbstractInstrumentReading {
12 |
13 | /** Constants. */
14 | public static final String TABLE_NAME = "spacecraft_location_over_time";
15 | public static final String COLUMN_LOCATION = "location";
16 | public static final String COLUMN_LOCATION_UNIT = "location_unit";
17 |
18 | @CqlName(COLUMN_LOCATION)
19 | private LocationUdt location;
20 |
21 | @CqlName(COLUMN_LOCATION_UNIT)
22 | private String location_unit;
23 |
24 | /**
25 | * Getter accessor for attribute 'location'.
26 | *
27 | * @return
28 | * current value of 'location'
29 | */
30 | public LocationUdt getLocation() {
31 | return location;
32 | }
33 |
34 | /**
35 | * Setter accessor for attribute 'location'.
36 | * @param location
37 | * new value for 'location '
38 | */
39 | public void setLocation(LocationUdt location) {
40 | this.location = location;
41 | }
42 |
43 | /**
44 | * Getter accessor for attribute 'location_unit'.
45 | *
46 | * @return
47 | * current value of 'location_unit'
48 | */
49 | public String getLocation_unit() {
50 | return location_unit;
51 | }
52 |
53 | /**
54 | * Setter accessor for attribute 'location_unit'.
55 | * @param location_unit
56 | * new value for 'location_unit '
57 | */
58 | public void setLocation_unit(String location_unit) {
59 | this.location_unit = location_unit;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/entity/SpacecraftPressureOverTime.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.entity;
2 |
3 | import com.datastax.oss.driver.api.mapper.annotations.CqlName;
4 | import com.datastax.oss.driver.api.mapper.annotations.Entity;
5 |
6 | /**
7 | * Bean Mapping table spacecraft_temperature_over_time.
8 | */
9 | @Entity
10 | @CqlName(SpacecraftPressureOverTime.TABLE_NAME)
11 | public class SpacecraftPressureOverTime extends AbstractInstrumentReading {
12 |
13 | /** Constants. */
14 | public static final String TABLE_NAME = "spacecraft_pressure_over_time";
15 | public static final String COLUMN_PRESSURE = "pressure";
16 | public static final String COLUMN_PRESSURE_UNIT = "pressure_unit";
17 |
18 | @CqlName(COLUMN_PRESSURE)
19 | private Double pressure;
20 |
21 | @CqlName(COLUMN_PRESSURE_UNIT)
22 | private String pressure_unit;
23 |
24 | /**
25 | * Getter accessor for attribute 'pressure'.
26 | *
27 | * @return
28 | * current value of 'pressure'
29 | */
30 | public Double getPressure() {
31 | return pressure;
32 | }
33 |
34 | /**
35 | * Setter accessor for attribute 'pressure'.
36 | * @param pressure
37 | * new value for 'pressure '
38 | */
39 | public void setPressure(Double pressure) {
40 | this.pressure = pressure;
41 | }
42 |
43 | /**
44 | * Getter accessor for attribute 'pressure_unit'.
45 | *
46 | * @return
47 | * current value of 'pressure_unit'
48 | */
49 | public String getPressure_unit() {
50 | return pressure_unit;
51 | }
52 |
53 | /**
54 | * Setter accessor for attribute 'pressure_unit'.
55 | * @param pressure_unit
56 | * new value for 'pressure_unit '
57 | */
58 | public void setPressure_unit(String pressure_unit) {
59 | this.pressure_unit = pressure_unit;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/entity/SpacecraftSpeedOverTime.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.entity;
2 |
3 | import com.datastax.oss.driver.api.mapper.annotations.CqlName;
4 | import com.datastax.oss.driver.api.mapper.annotations.Entity;
5 |
6 | /**
7 | * Bean Mapping table spacecraft_temperature_over_time.
8 | */
9 | @Entity
10 | @CqlName(SpacecraftSpeedOverTime.TABLE_NAME)
11 | public class SpacecraftSpeedOverTime extends AbstractInstrumentReading {
12 |
13 | /** Constants. */
14 | public static final String TABLE_NAME = "spacecraft_speed_over_time";
15 | public static final String COLUMN_SPEED = "speed";
16 | public static final String COLUMN_SPEED_UNIT = "speed_unit";
17 |
18 | @CqlName(COLUMN_SPEED)
19 | private Double speed;
20 |
21 | @CqlName(COLUMN_SPEED_UNIT)
22 | private String speed_unit;
23 |
24 | /**
25 | * Getter accessor for attribute 'speed'.
26 | *
27 | * @return
28 | * current value of 'speed'
29 | */
30 | public Double getSpeed() {
31 | return speed;
32 | }
33 |
34 | /**
35 | * Setter accessor for attribute 'speed'.
36 | * @param speed
37 | * new value for 'speed '
38 | */
39 | public void setSpeed(Double speed) {
40 | this.speed = speed;
41 | }
42 |
43 | /**
44 | * Getter accessor for attribute 'speed_unit'.
45 | *
46 | * @return
47 | * current value of 'speed_unit'
48 | */
49 | public String getSpeed_unit() {
50 | return speed_unit;
51 | }
52 |
53 | /**
54 | * Setter accessor for attribute 'speed_unit'.
55 | * @param speed_unit
56 | * new value for 'speed_unit '
57 | */
58 | public void setSpeed_unit(String speed_unit) {
59 | this.speed_unit = speed_unit;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/entity/SpacecraftTemperatureOverTime.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.entity;
2 |
3 | import com.datastax.oss.driver.api.mapper.annotations.CqlName;
4 | import com.datastax.oss.driver.api.mapper.annotations.Entity;
5 |
6 | /**
7 | * Bean Mapping table spacecraft_temperature_over_time.
8 | */
9 | @Entity
10 | @CqlName(SpacecraftTemperatureOverTime.TABLE_NAME)
11 | public class SpacecraftTemperatureOverTime extends AbstractInstrumentReading {
12 |
13 | /** Constants. */
14 | public static final String TABLE_NAME = "spacecraft_temperature_over_time";
15 | public static final String COLUMN_TEMPERATURE = "temperature";
16 | public static final String COLUMN_TEMPERATURE_UNIT = "temperature_unit";
17 |
18 | @CqlName(COLUMN_TEMPERATURE)
19 | private Double temperature;
20 |
21 | @CqlName(COLUMN_TEMPERATURE_UNIT)
22 | private String temperature_unit;
23 |
24 | /**
25 | * Getter accessor for attribute 'temperature'.
26 | *
27 | * @return
28 | * current value of 'temperature'
29 | */
30 | public Double getTemperature() {
31 | return temperature;
32 | }
33 |
34 | /**
35 | * Setter accessor for attribute 'temperature'.
36 | * @param temperature
37 | * new value for 'temperature '
38 | */
39 | public void setTemperature(Double temperature) {
40 | this.temperature = temperature;
41 | }
42 |
43 | /**
44 | * Getter accessor for attribute 'temperature_unit'.
45 | *
46 | * @return
47 | * current value of 'temperature_unit'
48 | */
49 | public String getTemperature_unit() {
50 | return temperature_unit;
51 | }
52 |
53 | /**
54 | * Setter accessor for attribute 'temperature_unit'.
55 | * @param temperature_unit
56 | * new value for 'temperature_unit '
57 | */
58 | public void setTemperature_unit(String temperature_unit) {
59 | this.temperature_unit = temperature_unit;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/model/PagedResultWrapper.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.model;
2 |
3 | import java.nio.ByteBuffer;
4 | import java.util.ArrayList;
5 | import java.util.Iterator;
6 | import java.util.List;
7 | import java.util.Optional;
8 | import java.util.stream.IntStream;
9 |
10 | import com.datastax.oss.driver.api.core.MappedAsyncPagingIterable;
11 | import com.datastax.oss.driver.api.core.PagingIterable;
12 | import com.datastax.oss.protocol.internal.util.Bytes;
13 |
14 | /**
15 | * Ease usage of the paginState.
16 | *
17 | * @author DataStax Developer Advocates team.
18 | */
19 | public class PagedResultWrapper < ENTITY > {
20 |
21 | /** Custom management of paging state. */
22 | private Optional< String > pageState = Optional.empty();
23 |
24 | /** Custom management of paging state. */
25 | private Integer pageSize = 1;
26 |
27 | /** Results map as entities. */
28 | private List data = new ArrayList<>();
29 |
30 | /**
31 | * Default Constructor.
32 | */
33 | public PagedResultWrapper() {}
34 |
35 | /**
36 | * Constructor from a RESULT.
37 | *
38 | * @param rs
39 | * result set
40 | * @param mapper
41 | * mapper
42 | */
43 | public PagedResultWrapper(PagingIterable rs, int pageSize) {
44 | if (null != rs) {
45 | Iterator iterResults = rs.iterator();
46 | IntStream.range(0, rs.getAvailableWithoutFetching())
47 | .forEach(item -> data.add(iterResults.next()));
48 | if (null != rs.getExecutionInfo().getPagingState()) {
49 | ByteBuffer pagingState = rs.getExecutionInfo().getPagingState();
50 | if (pagingState != null && pagingState.hasArray()) {
51 | pageState = Optional.ofNullable(Bytes.toHexString(pagingState));
52 | }
53 | }
54 | this.pageSize = pageSize;
55 | }
56 | }
57 |
58 | public PagedResultWrapper(MappedAsyncPagingIterable rs, int pageSize) {
59 | if (null != rs) {
60 | rs.currentPage().forEach(data::add);
61 | ByteBuffer pagingState = rs.getExecutionInfo().getPagingState();
62 | if (pagingState != null && pagingState.hasArray()) {
63 | pageState = Optional.ofNullable(Bytes.toHexString(pagingState));
64 | }
65 | this.pageSize = pageSize;
66 | }
67 | }
68 |
69 | /**
70 | * Getter accessor for attribute 'pageState'.
71 | *
72 | * @return
73 | * current value of 'pageState'
74 | */
75 | public Optional getPageState() {
76 | return pageState;
77 | }
78 |
79 | /**
80 | * Getter accessor for attribute 'pageSize'.
81 | *
82 | * @return
83 | * current value of 'pageSize'
84 | */
85 | public Integer getPageSize() {
86 | return pageSize;
87 | }
88 |
89 | /**
90 | * Getter accessor for attribute 'data'.
91 | *
92 | * @return
93 | * current value of 'data'
94 | */
95 | public List getData() {
96 | return data;
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/service/AstraService.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.service;
2 |
3 | import java.time.Instant;
4 | import java.time.temporal.ChronoUnit;
5 | import java.util.List;
6 | import java.util.Optional;
7 | import java.util.UUID;
8 |
9 | import javax.annotation.PreDestroy;
10 |
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 | import org.springframework.stereotype.Component;
14 |
15 | import com.datastax.astra.dao.SessionManager;
16 | import com.datastax.astra.dao.SpacecraftInstrumentsDao;
17 | import com.datastax.astra.dao.SpacecraftJourneyDao;
18 | import com.datastax.astra.dao.SpacecraftMapper;
19 | import com.datastax.astra.dao.SpacecraftMapperBuilder;
20 | import com.datastax.astra.entity.SpacecraftJourneyCatalog;
21 | import com.datastax.astra.entity.SpacecraftLocationOverTime;
22 | import com.datastax.astra.entity.SpacecraftPressureOverTime;
23 | import com.datastax.astra.entity.SpacecraftSpeedOverTime;
24 | import com.datastax.astra.entity.SpacecraftTemperatureOverTime;
25 | import com.datastax.astra.model.PagedResultWrapper;
26 | import com.datastax.oss.driver.api.core.CqlSession;
27 | import com.datastax.oss.driver.api.core.PagingIterable;
28 | import com.datastax.oss.driver.api.core.uuid.Uuids;
29 |
30 | /**
31 | * Implementation of Service for controller
32 | *
33 | */
34 | @Component
35 | public class AstraService {
36 |
37 | /** Logger for the class. */
38 | private static final Logger LOGGER = LoggerFactory.getLogger(AstraService.class);
39 |
40 | /** Driver Daos. */
41 | private SpacecraftJourneyDao spacecraftJourneyDao;
42 | private SpacecraftInstrumentsDao spacecraftInstrumentsDao;
43 |
44 | /**
45 | * Find all spacecrafts in the catalog.
46 | */
47 | public List< SpacecraftJourneyCatalog > findAllSpacecrafts() {
48 | // no paging we don't expect more than 5k journeys
49 | return getSpaceCraftJourneyDao().findAll().all();
50 | }
51 |
52 | /**
53 | * Find all journeys for a spacecraft.
54 | *
55 | * @param spacecraftName
56 | * unique spacecraft name (PK)
57 | * @return
58 | * list of journeys
59 | */
60 | public List < SpacecraftJourneyCatalog > findAllJourneysForSpacecraft(String spacecraftName) {
61 | // no paging we don't expect more than 5k journeys
62 | return getSpaceCraftJourneyDao().findAllJourneysForSpacecraft(spacecraftName).all();
63 | }
64 |
65 | /**
66 | * Search by primary key, unique record expect.
67 | *
68 | * @param spacecraftName
69 | * unique spacecraft name (PK)
70 | * @param journeyid
71 | * journey unique identifier
72 | * @return
73 | * journey details if it exists
74 | */
75 | public Optional< SpacecraftJourneyCatalog > findJourneyById(String spacecraftName, UUID journeyId) {
76 | return getSpaceCraftJourneyDao().findById(spacecraftName, journeyId);
77 | }
78 |
79 | /**
80 | * Create a new {@link SpacecraftJourneyCatalog}.
81 | *
82 | * @param spacecraftName
83 | * unique spacecraft name (PK)
84 | * @param summary
85 | * short description
86 | * @return
87 | * generated journey id
88 | */
89 | public UUID createSpacecraftJourney(String spacecraftName, String summary) {
90 | UUID journeyUid = Uuids.timeBased();
91 | LOGGER.debug("Creating journey {} for spacecraft {}", journeyUid, spacecraftName);
92 | SpacecraftJourneyCatalog dto = new SpacecraftJourneyCatalog();
93 | dto.setName(spacecraftName);
94 | dto.setSummary(summary);
95 | dto.setStart(Instant.now());
96 | dto.setEnd(Instant.now().plus(1000, ChronoUnit.MINUTES));
97 | dto.setActive(false);
98 | dto.setJourneyId(journeyUid);
99 | getSpaceCraftJourneyDao().upsert(dto);
100 | return journeyUid;
101 | }
102 |
103 | /**
104 | * Retrieve temperature readings for a journey.
105 | *
106 | * @param spacecraftName
107 | * name of spacecrafr
108 | * @param journeyId
109 | * journey identifier
110 | * @param pageSize
111 | * page size
112 | * @param pageState
113 | * page state
114 | * @return
115 | * result page
116 | */
117 | public PagedResultWrapper getTemperatureReading(
118 | String spacecraftName, UUID journeyId,
119 | Optional pageSize, Optional pageState) {
120 | PagingIterable daoResult =
121 | getSpaceCraftInstrumentsDao().getTemperatureReading(spacecraftName, journeyId, pageSize, pageState);
122 | return new PagedResultWrapper(daoResult,
123 | pageSize.isPresent() ? pageSize.get() : 0);
124 | }
125 |
126 | /**
127 | * Create a new {@link SpacecraftTemperatureOverTime} for each item in the array.
128 | *
129 | * @param readings
130 | * An array unique temperature readings
131 | * @return
132 | * true if successful
133 | */
134 | public void insertTemperatureReading(SpacecraftTemperatureOverTime[] readings) {
135 | long top = System.currentTimeMillis();
136 | getSpaceCraftInstrumentsDao().insertTemperatureReadingAsync(readings)
137 | .whenComplete((res,ex) -> LOGGER.debug("{} temperature reading(s) inserted in {} millis",
138 | readings.length, System.currentTimeMillis() - top));
139 | }
140 |
141 | /**
142 | * Create a new {@link SpacecraftLocationOverTime} for each item in the array.
143 | *
144 | * @param readings
145 | * An array unique location readings
146 | * @return
147 | * true if successful
148 | */
149 | public void insertLocationReading(SpacecraftLocationOverTime[] readings) {
150 | long top = System.currentTimeMillis();
151 | getSpaceCraftInstrumentsDao()
152 | .insertLocationReadingAsync(readings)
153 | .whenComplete((res,ex) -> LOGGER.debug("{} location reading(s) inserted in {} millis",
154 | readings.length, System.currentTimeMillis() - top));
155 | }
156 |
157 | /**
158 | * Create a new {@link SpacecraftPressureOverTime} for each item in the array.
159 | *
160 | * @param readings
161 | * An array unique pressure readings
162 | * @return
163 | * true if successful
164 | */
165 | public void insertPressureReading(SpacecraftPressureOverTime[] readings) {
166 | long top = System.currentTimeMillis();
167 | getSpaceCraftInstrumentsDao()
168 | .insertPressureReadingAsync(readings)
169 | .whenComplete((res,ex) -> LOGGER.debug("{} pressure reading(s) inserted in {} millis",
170 | readings.length, System.currentTimeMillis() - top));
171 | }
172 |
173 | /**
174 | * Create a new {@link SpacecraftSpeedOverTime} for each item in the array.
175 | *
176 | * @param readings
177 | * An array unique pressure readings
178 | * @return
179 | * true if successful
180 | */
181 | public void insertSpeedReading(SpacecraftSpeedOverTime[] readings) {
182 | long top = System.currentTimeMillis();
183 | getSpaceCraftInstrumentsDao()
184 | .insertSpeedReadingAsync(readings)
185 | .whenComplete((res,ex) -> LOGGER.debug("{} speed reading(s) inserted in {} millis",
186 | readings.length, System.currentTimeMillis() - top));
187 | }
188 |
189 | /**
190 | * Retrieve pressure readings for a journey.
191 | *
192 | * @param spacecraftName
193 | * name of spacecrafr
194 | * @param journeyId
195 | * journey identifier
196 | * @param pageSize
197 | * page size
198 | * @param pageState
199 | * page state
200 | * @return
201 | * result page
202 | */
203 | public PagedResultWrapper getPressureReading(
204 | String spacecraftName, UUID journeyId,
205 | Optional pageSize, Optional pageState) {
206 | PagingIterable daoResult =
207 | getSpaceCraftInstrumentsDao().getPressureReading(spacecraftName, journeyId, pageSize, pageState);
208 | return new PagedResultWrapper(daoResult,
209 | pageSize.isPresent() ? pageSize.get() : 0);
210 | }
211 |
212 | /**
213 | * Retrieve speed readings for a journey.
214 | *
215 | * @param spacecraftName
216 | * name of spacecrafr
217 | * @param journeyId
218 | * journey identifier
219 | * @param pageSize
220 | * page size
221 | * @param pageState
222 | * page state
223 | * @return
224 | * result page
225 | */
226 | public PagedResultWrapper getSpeedReading(
227 | String spacecraftName, UUID journeyId,
228 | Optional pageSize, Optional pageState) {
229 | PagingIterable daoResult =
230 | getSpaceCraftInstrumentsDao().getSpeedReading(spacecraftName, journeyId, pageSize, pageState);
231 | return new PagedResultWrapper(daoResult,
232 | pageSize.isPresent() ? pageSize.get() : 0);
233 | }
234 |
235 | /**
236 | * Retrieve speed readings for a journey.
237 | *
238 | * @param spacecraftName
239 | * name of spacecrafr
240 | * @param journeyId
241 | * journey identifier
242 | * @param pageSize
243 | * page size
244 | * @param pageState
245 | * page state
246 | * @return
247 | * result page
248 | */
249 | public PagedResultWrapper getLocationReading(
250 | String spacecraftName, UUID journeyId,
251 | Optional pageSize, Optional pageState) {
252 | PagingIterable daoResult =
253 | getSpaceCraftInstrumentsDao().getLocationReading(spacecraftName, journeyId, pageSize, pageState);
254 | return new PagedResultWrapper(daoResult,
255 | pageSize.isPresent() ? pageSize.get() : 0);
256 | }
257 |
258 | protected synchronized SpacecraftJourneyDao getSpaceCraftJourneyDao() {
259 | if (spacecraftJourneyDao == null) {
260 | CqlSession cqlSession = SessionManager.getInstance().connectToAstra();
261 | SpacecraftMapper mapper = new SpacecraftMapperBuilder(cqlSession).build();
262 | this.spacecraftJourneyDao = mapper.spacecraftJourneyDao(cqlSession.getKeyspace().get());
263 | }
264 | return spacecraftJourneyDao;
265 | }
266 |
267 | protected synchronized SpacecraftInstrumentsDao getSpaceCraftInstrumentsDao() {
268 | if (spacecraftInstrumentsDao == null) {
269 | CqlSession cqlSession = SessionManager.getInstance().connectToAstra();
270 | SpacecraftMapper mapper = new SpacecraftMapperBuilder(cqlSession).build();
271 | this.spacecraftInstrumentsDao = mapper.spacecraftInstrumentsDao(cqlSession.getKeyspace().get());
272 | }
273 | return spacecraftInstrumentsDao;
274 | }
275 |
276 | /**
277 | * Properly close CqlSession
278 | */
279 | @PreDestroy
280 | public void cleanUp() {
281 | SessionManager.getInstance().close();
282 | }
283 |
284 | }
285 |
--------------------------------------------------------------------------------
/src/main/java/com/datastax/astra/utils/CqlFileUtils.java:
--------------------------------------------------------------------------------
1 | package com.datastax.astra.utils;
2 |
3 | import java.io.FileNotFoundException;
4 | import java.io.InputStream;
5 | import java.util.Arrays;
6 | import java.util.Scanner;
7 |
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import com.datastax.oss.driver.api.core.CqlSession;
12 | import com.datastax.oss.driver.api.core.servererrors.InvalidQueryException;
13 |
14 | /**
15 | * Allow to execute a CQL File
16 | */
17 | public class CqlFileUtils {
18 |
19 | private static final Logger LOGGER = LoggerFactory.getLogger(CqlFileUtils.class);
20 |
21 | /** Helper for CQL FILE. */
22 | private static final String UTF8_ENCODING = "UTF-8";
23 | private static final String NEW_LINE = System.getProperty("line.separator");
24 |
25 | /**
26 | * Utils method to load a file as String.
27 | *
28 | * @param fileName
29 | * target file Name.
30 | * @return target file content as String
31 | * @throws FileNotFoundException
32 | */
33 | private static String loadFileAsString(String fileName)
34 | throws FileNotFoundException {
35 | InputStream in = CqlFileUtils.class.getResourceAsStream(fileName);
36 | if (in == null) {
37 | // Fetch absolute classloader path
38 | in = CqlFileUtils.class.getClassLoader().getResourceAsStream(fileName);
39 | }
40 | if (in == null) {
41 | // Thread
42 | in = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
43 | }
44 | if (in == null) {
45 | throw new FileNotFoundException("Cannot load file " + fileName + " please check");
46 | }
47 | Scanner currentScan = null;
48 | StringBuilder strBuilder = new StringBuilder();
49 | try {
50 | currentScan = new Scanner(in, UTF8_ENCODING);
51 | while (currentScan.hasNextLine()) {
52 | strBuilder.append(currentScan.nextLine());
53 | strBuilder.append(NEW_LINE);
54 | }
55 | } finally {
56 | if (currentScan != null) {
57 | currentScan.close();
58 | }
59 | }
60 | return strBuilder.toString();
61 | }
62 |
63 | /**
64 | * Allows to execute a CQL File.
65 | *
66 | * @param dseSession
67 | * current dse Session
68 | * @param fileName
69 | * cql file name to execute
70 | * @throws FileNotFoundException
71 | * cql file has not been found.
72 | */
73 | public static void executeCQLFile(CqlSession cqlSession, String fileName)
74 | throws FileNotFoundException {
75 | long top = System.currentTimeMillis();
76 | Arrays.stream(loadFileAsString(fileName).split(";")).forEach(statement -> {
77 | String query = statement.replaceAll(NEW_LINE, "").trim();
78 | try {
79 | if (query.length() > 0) {
80 | cqlSession.execute(query);
81 | LOGGER.info(" + Executed. " + query);
82 | }
83 | } catch (InvalidQueryException e) {
84 | LOGGER.warn(" + Query Ignore. " + query, e);
85 | }
86 | });
87 | LOGGER.info("Execution done in {} millis.", System.currentTimeMillis() - top);
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/resources/application.conf:
--------------------------------------------------------------------------------
1 | datastax-java-driver {
2 |
3 | basic {
4 |
5 | # Raising read timeout anticipating low bandwith
6 | request.timeout = 8 seconds
7 |
8 | # Consistency Level by default for Astra
9 | request.consistency = LOCAL_QUORUM
10 | }
11 |
12 | }
--------------------------------------------------------------------------------
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | # ----------------------------------------------------------
2 | # Spring Boot Config
3 | # ----------------------------------------------------------
4 | spring:
5 | application:
6 | name: Getting Started with Astra
7 | jackson:
8 | serialization:
9 | WRITE_DATES_AS_TIMESTAMPS: false
10 | server:
11 | port: 8080
12 |
--------------------------------------------------------------------------------
/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 | ${AnsiColor.RED} ___ _
2 | ${AnsiColor.RED} / _ \ | |
3 | ${AnsiColor.RED} / /_\ \ ___ | |_ _ __ __ _
4 | ${AnsiColor.RED} | _ |/ __|| __|| '__| / _` |
5 | ${AnsiColor.RED} | | | |\__ \| |_ | | | (_| |
6 | ${AnsiColor.RED} \_| |_/|___/ \__||_| \__,_|
7 | ${AnsiColor.BLUE}
8 | ${AnsiColor.BLUE} Getting Started with Astra
9 |
10 |
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | %d{HH:mm:ss.SSS} %magenta(%-5level) %cyan(%-45logger) : %msg%n
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/resources/schema.cql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS spacecraft_journey_catalog (
2 | spacecraft_name text,
3 | journey_id timeuuid,
4 | start timestamp,
5 | end timestamp,
6 | active boolean,
7 | summary text,
8 | PRIMARY KEY ((spacecraft_name), journey_id)
9 | ) WITH CLUSTERING ORDER BY (journey_id desc);
10 |
11 | CREATE TABLE IF NOT EXISTS spacecraft_speed_over_time (
12 | spacecraft_name text,
13 | journey_id timeuuid,
14 | speed double,
15 | reading_time timestamp,
16 | speed_unit text,
17 | PRIMARY KEY ((spacecraft_name, journey_id), reading_time)
18 | ) WITH CLUSTERING ORDER BY (reading_time DESC);
19 |
20 | CREATE TABLE IF NOT EXISTS spacecraft_temperature_over_time (
21 | spacecraft_name text,
22 | journey_id timeuuid,
23 | temperature double,
24 | temperature_unit text,
25 | reading_time timestamp,
26 | PRIMARY KEY ((spacecraft_name, journey_id), reading_time)
27 | ) WITH CLUSTERING ORDER BY (reading_time DESC);
28 |
29 | CREATE TABLE IF NOT EXISTS spacecraft_pressure_over_time (
30 | spacecraft_name text,
31 | journey_id timeuuid,
32 | pressure double,
33 | pressure_unit text,
34 | reading_time timestamp,
35 | PRIMARY KEY ((spacecraft_name, journey_id), reading_time)
36 | ) WITH CLUSTERING ORDER BY (reading_time DESC);
37 |
38 | CREATE TYPE IF NOT EXISTS location_udt (
39 | x_coordinate double,
40 | y_coordinate double,
41 | z_coordinate double);
42 |
43 | CREATE TABLE IF NOT EXISTS spacecraft_location_over_time (
44 | spacecraft_name text,
45 | journey_id timeuuid,
46 | location frozen,
47 | location_unit text,
48 | reading_time timestamp,
49 | PRIMARY KEY ((spacecraft_name, journey_id), reading_time)
50 | ) WITH CLUSTERING ORDER BY (reading_time DESC);
51 |
--------------------------------------------------------------------------------