Skip to content

Commit

Permalink
Merge pull request #36 from oracle/helidon-v2.1.0
Browse files Browse the repository at this point in the history
Helidon v2.1.0
  • Loading branch information
jeandelavarene authored Sep 10, 2024
2 parents 56b0366 + feb456a commit a870645
Show file tree
Hide file tree
Showing 21 changed files with 390 additions and 304 deletions.
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;

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

0 comments on commit a870645

Please sign in to comment.