Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Helidon v2.1.0 #36

Merged
merged 16 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions mtdrworkshop/backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Todolist Helidon backend

Todolist application backend built with Helidon SE, using Oracle JDBC
- __App Version `v2.1.0`__
- __Oracle JDBC Version `v23.4.0.24.05`__
- __Helidon SE Version `v2.4.2`__

## Environment Variables
The following environment variables are expected by the application.
In order to successfully run the application, the environment variables below are __REQUIRED__.

| Variable | Name | Default | Description |
|---------------------|-------------------|---------|-----------------------------------------------------------------|
| `database.url` | Database URL | - | Connection to URL, in the form of `jdbc:oracle:thin:@<details>` |
| `database.user` | Database User | - | Database user with access to the necessary tables |
| `database.password` | Database Password | - | Database user credentials |

## API Endpoints

The following endpoints are endpoints used by the application.

| Method | REST Endpoint | Sample Data | Description |
|--------|-------------------------------------------|----------------------------------------|-----------------------|
| GET | `http://localhost:8080/api/todolist` | - | Retrieves all Todos |
| POST | `http://localhost:8080/api/todolist` | `{"description" : "Second new task!"}` | Saves a new Todo |
| GET | `http://localhost:8080/api/todolist/{id}` | - | Retrieves a Todo item |
| PUT | `http://localhost:8080/api/todolist/{id}` | `{"description": "...", "done": true}` | Updates a Todo item |
| DELETE | `http://localhost:8080/api/todolist/{id}` | - | Deletes a Todo item |


## SQL Schema, Tables and Queries

The application expects and makes use of the following:

- __Database Schemas__: `TODOOWNER`
- __Database Tables__: `TODOITEM`
- __Database Queries and Privilege__:
- `select, insert, update, delete` on `TODOOWNER.TODOITEM`


# Building the Application
The application uses Maven to build and manage the project with its dependencies.
Since the [Dockerfile](./src/main/docker/Dockerfile) expects the JAR, you need to run mvn first.
```bash
mvn clean package
```

When building for docker, you can use the following command:
```bash
docker build -f src/main/docker/Dockerfile -t <image> .
```

# Deploying to Kubernetes
To deploy the application on Kubernetes,
the environment variables and image must be replaced.

For example, you can create the following manifest.yaml file:
```yaml
# manifest
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-deployment
labels:
app: backendapp
spec:
replicas: 1
selector:
matchLabels:
app: backendapp
template:
metadata:
labels:
app: backendapp
spec:
containers:
- name: app
image: example:v1 # update with your container image
env:
- name: database.user
value: myUser # update with your database user
- name: database.url
value: "jdbc:oracle:thin:@<details>" # update with your database URL
- name: database.password
valueFrom:
secretKeyRef:
name: myDatabasePWDSecret # update with your database secret
key: password
ports:
- containerPort: 8080

# if database wallet is required
volumeMounts:
- name: creds
mountPath: /app/creds # update with the right path to the wallet
# end if

restartPolicy: Always

# if database wallet is required
volumes:
- name: creds
secret:
secretName: db-wallet-secret # update with the actual secret
# end if


---

apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
type: ClusterIP
ports:
- port: 8080
targetPort: 8080
selector:
app: backendapp
```

This configuration requires the following secret to be created:
```bash
kubectl create secret generic myDatabasePWDSecret --from-literal=password=<value>
```

If a wallet is necessary, you can run the following command to create the wallet secret
```bash
kubectl create secret generic wallet --from-file=<wallet_location>
```
2 changes: 1 addition & 1 deletion mtdrworkshop/backend/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ mvn clean package
docker build -f src/main/docker/Dockerfile -t $IMAGE .

if [ $? -ne 0 ]; then
exit 1
exit 1
fi
docker push $IMAGE
4 changes: 2 additions & 2 deletions mtdrworkshop/backend/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ mv -- /tmp/"$YAML_NAME" "$YAML_NAME"


if [ -z "$1" ]; then
kubectl apply -f $SCRIPT_DIR/"$YAML_NAME" -n mtdrworkshop
kubectl apply -f $SCRIPT_DIR/"$YAML_NAME" -n mtdrworkshop
else
kubectl apply -f <(istioctl kube-inject -f $SCRIPT_DIR/"$YAML_NAME") -n mtdrworkshop
kubectl apply -f <(istioctl kube-inject -f $SCRIPT_DIR/"$YAML_NAME") -n mtdrworkshop
fi

#kubectl apply -f $SCRIPT_DIR/order-service.yaml -n mtdrworkshop
Expand Down
53 changes: 20 additions & 33 deletions mtdrworkshop/backend/pom.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
## MyToDoReact version 1.0.
## MyToDoReact version 2.1.0
##
## Copyright (c) 2021 Oracle, Inc.
## Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
## Copyright (c) 2024 Oracle, Inc.
## Licensed under the Universal Permissive License v1.0 as shown at https://oss.oracle.com/licenses/upl/
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
Expand Down Expand Up @@ -99,13 +99,25 @@
</build>

<dependencies>
<!-- added by peter song for database connection-->
<!-- database connection dependencies -->
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-common</artifactId>
<version>1.32.2</version>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc11</artifactId>
<version>23.4.0.24.05</version>
</dependency>
<!-- added by peter song for database connection-->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ucp11</artifactId>
<version>23.4.0.24.05</version>
</dependency>
<dependency>
<groupId>com.oracle.database.security</groupId>
<artifactId>oraclepki</artifactId>
<version>23.4.0.24.05</version>
</dependency>


<!-- helidon dependencies -->
<dependency>
<groupId>io.helidon.webserver</groupId>
<artifactId>helidon-webserver-cors</artifactId>
Expand All @@ -126,31 +138,6 @@
<groupId>io.helidon.health</groupId>
<artifactId>helidon-health-checks</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ojdbc10</artifactId>
<version>19.3.0.0</version>
</dependency>
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ucp</artifactId>
<version>19.3.0.0</version>
</dependency>
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>osdt_core</artifactId>
<version>19.3.0.0</version>
</dependency>
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>osdt_cert</artifactId>
<version>19.3.0.0</version>
</dependency>
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>oraclepki</artifactId>
<version>19.3.0.0</version>
</dependency>
</dependencies>

</project>
20 changes: 10 additions & 10 deletions mtdrworkshop/backend/set.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,28 @@ export IMAGE_NAME=todolistapp-helidon-se
export IMAGE_VERSION=0.1

if [ -z "$DOCKER_REGISTRY" ]; then
echo "DOCKER_REGISTRY not set. Will get it with state_get"
echo "DOCKER_REGISTRY not set. Will get it with state_get"
export DOCKER_REGISTRY=$(state_get DOCKER_REGISTRY)
fi

if [ -z "$DOCKER_REGISTRY" ]; then
echo "Error: DOCKER_REGISTRY env variable needs to be set!"
exit 1
echo "Error: DOCKER_REGISTRY env variable needs to be set!"
exit 1
fi
if [ -z "$TODO_PDB_NAME" ]; then
echo "TODO_PDB_NAME not set. Will get it with state_get"
echo "TODO_PDB_NAME not set. Will get it with state_get"
export TODO_PDB_NAME=$(state_get MTDR_DB_NAME)
fi
if [ -z "$TODO_PDB_NAME" ]; then
echo "Error: TODO_PDB_NAME env variable needs to be set!"
exit 1
echo "Error: TODO_PDB_NAME env variable needs to be set!"
exit 1
fi
if [ -z "$OCI_REGION" ]; then
echo "OCI_REGION not set. Will get it with state_get"
export OCI_REGION=$(state_get REGION)
echo "OCI_REGION not set. Will get it with state_get"
export OCI_REGION=$(state_get REGION)
fi
if [ -z "$OCI_REGION" ]; then
echo "Error: OCI_REGION env variable needs to be set!"
exit 1
echo "Error: OCI_REGION env variable needs to be set!"
exit 1
fi
export IMAGE=${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_VERSION}
9 changes: 9 additions & 0 deletions mtdrworkshop/backend/sql/todoitem.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CREATE TABLE TODOOWNER.TODOITEM (
ID NUMBER GENERATED ALWAYS AS IDENTITY,
DESCRIPTION VARCHAR2(4000),
CREATION_TS TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
DONE NUMBER(1, 0) DEFAULT 0,
PRIMARY KEY (ID)
);

INSERT INTO TODOOWNER.TODOITEM (DESCRIPTION) VALUES ('My first task!');
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
## MyToDoReact version 2.1.0
##
## Copyright (c) 2024 Oracle, Inc.
## Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
*/
package com.oracle.database;
aberinnj marked this conversation as resolved.
Show resolved Hide resolved

import io.helidon.config.Config;
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class AppDatasource {

// connection pooling using UCP
private final PoolDataSource pds;
private static AppDatasource instance = null;

// static get
public synchronized static AppDatasource get(Config c) {
if (instance == null) {
instance = new AppDatasource(c);
}
return instance;
}

// constructor, initialize datasource
private AppDatasource(Config c) {
this.pds = PoolDataSourceFactory.getPoolDataSource();
String url = c.get("url").asString().orElse("");
String username = c.get("user").asString().orElse("");
String password = c.get("password").asString().orElse("");

try {

// In this application, we don't set any init, min or max size in UCP. We
// also don't start the pool explicitly. This means that the very first
// connection request will start the pool. The default maximum pool size
// is MAX_INT which isn't appropriate and should be configured properly in
// production.
this.pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
this.pds.setConnectionPoolName("JDBC_UCP_POOL");
this.pds.setInactiveConnectionTimeout(60);
this.pds.setMaxStatements(10);

// if provided, set
if (!url.isEmpty()) {
this.pds.setURL(url);
}
if (!username.isEmpty()) {
this.pds.setUser(username);
}
if (!password.isEmpty()) {
this.pds.setPassword(password);
}

} catch (SQLException e) {
throw new RuntimeException(e);
}
}

// retrieve connection
public Connection getConnection() throws SQLException {
return this.pds.getConnection();
}

}
Loading