Skip to content

Commit a870645

Browse files
Merge pull request #36 from oracle/helidon-v2.1.0
Helidon v2.1.0
2 parents 56b0366 + feb456a commit a870645

File tree

21 files changed

+390
-304
lines changed

21 files changed

+390
-304
lines changed

mtdrworkshop/backend/README.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Todolist Helidon backend
2+
3+
Todolist application backend built with Helidon SE, using Oracle JDBC
4+
- __App Version `v2.1.0`__
5+
- __Oracle JDBC Version `v23.4.0.24.05`__
6+
- __Helidon SE Version `v2.4.2`__
7+
8+
## Environment Variables
9+
The following environment variables are expected by the application.
10+
In order to successfully run the application, the environment variables below are __REQUIRED__.
11+
12+
| Variable | Name | Default | Description |
13+
|---------------------|-------------------|---------|-----------------------------------------------------------------|
14+
| `database.url` | Database URL | - | Connection to URL, in the form of `jdbc:oracle:thin:@<details>` |
15+
| `database.user` | Database User | - | Database user with access to the necessary tables |
16+
| `database.password` | Database Password | - | Database user credentials |
17+
18+
## API Endpoints
19+
20+
The following endpoints are endpoints used by the application.
21+
22+
| Method | REST Endpoint | Sample Data | Description |
23+
|--------|-------------------------------------------|----------------------------------------|-----------------------|
24+
| GET | `http://localhost:8080/api/todolist` | - | Retrieves all Todos |
25+
| POST | `http://localhost:8080/api/todolist` | `{"description" : "Second new task!"}` | Saves a new Todo |
26+
| GET | `http://localhost:8080/api/todolist/{id}` | - | Retrieves a Todo item |
27+
| PUT | `http://localhost:8080/api/todolist/{id}` | `{"description": "...", "done": true}` | Updates a Todo item |
28+
| DELETE | `http://localhost:8080/api/todolist/{id}` | - | Deletes a Todo item |
29+
30+
31+
## SQL Schema, Tables and Queries
32+
33+
The application expects and makes use of the following:
34+
35+
- __Database Schemas__: `TODOOWNER`
36+
- __Database Tables__: `TODOITEM`
37+
- __Database Queries and Privilege__:
38+
- `select, insert, update, delete` on `TODOOWNER.TODOITEM`
39+
40+
41+
# Building the Application
42+
The application uses Maven to build and manage the project with its dependencies.
43+
Since the [Dockerfile](./src/main/docker/Dockerfile) expects the JAR, you need to run mvn first.
44+
```bash
45+
mvn clean package
46+
```
47+
48+
When building for docker, you can use the following command:
49+
```bash
50+
docker build -f src/main/docker/Dockerfile -t <image> .
51+
```
52+
53+
# Deploying to Kubernetes
54+
To deploy the application on Kubernetes,
55+
the environment variables and image must be replaced.
56+
57+
For example, you can create the following manifest.yaml file:
58+
```yaml
59+
# manifest
60+
apiVersion: apps/v1
61+
kind: Deployment
62+
metadata:
63+
name: backend-deployment
64+
labels:
65+
app: backendapp
66+
spec:
67+
replicas: 1
68+
selector:
69+
matchLabels:
70+
app: backendapp
71+
template:
72+
metadata:
73+
labels:
74+
app: backendapp
75+
spec:
76+
containers:
77+
- name: app
78+
image: example:v1 # update with your container image
79+
env:
80+
- name: database.user
81+
value: myUser # update with your database user
82+
- name: database.url
83+
value: "jdbc:oracle:thin:@<details>" # update with your database URL
84+
- name: database.password
85+
valueFrom:
86+
secretKeyRef:
87+
name: myDatabasePWDSecret # update with your database secret
88+
key: password
89+
ports:
90+
- containerPort: 8080
91+
92+
# if database wallet is required
93+
volumeMounts:
94+
- name: creds
95+
mountPath: /app/creds # update with the right path to the wallet
96+
# end if
97+
98+
restartPolicy: Always
99+
100+
# if database wallet is required
101+
volumes:
102+
- name: creds
103+
secret:
104+
secretName: db-wallet-secret # update with the actual secret
105+
# end if
106+
107+
108+
---
109+
110+
apiVersion: v1
111+
kind: Service
112+
metadata:
113+
name: backend-service
114+
spec:
115+
type: ClusterIP
116+
ports:
117+
- port: 8080
118+
targetPort: 8080
119+
selector:
120+
app: backendapp
121+
```
122+
123+
This configuration requires the following secret to be created:
124+
```bash
125+
kubectl create secret generic myDatabasePWDSecret --from-literal=password=<value>
126+
```
127+
128+
If a wallet is necessary, you can run the following command to create the wallet secret
129+
```bash
130+
kubectl create secret generic wallet --from-file=<wallet_location>
131+
```

mtdrworkshop/backend/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ mvn clean package
1313
docker build -f src/main/docker/Dockerfile -t $IMAGE .
1414

1515
if [ $? -ne 0 ]; then
16-
exit 1
16+
exit 1
1717
fi
1818
docker push $IMAGE

mtdrworkshop/backend/deploy.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ mv -- /tmp/"$YAML_NAME" "$YAML_NAME"
3232

3333

3434
if [ -z "$1" ]; then
35-
kubectl apply -f $SCRIPT_DIR/"$YAML_NAME" -n mtdrworkshop
35+
kubectl apply -f $SCRIPT_DIR/"$YAML_NAME" -n mtdrworkshop
3636
else
37-
kubectl apply -f <(istioctl kube-inject -f $SCRIPT_DIR/"$YAML_NAME") -n mtdrworkshop
37+
kubectl apply -f <(istioctl kube-inject -f $SCRIPT_DIR/"$YAML_NAME") -n mtdrworkshop
3838
fi
3939

4040
#kubectl apply -f $SCRIPT_DIR/order-service.yaml -n mtdrworkshop

mtdrworkshop/backend/pom.xml

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
3-
## MyToDoReact version 1.0.
3+
## MyToDoReact version 2.1.0
44
##
5-
## Copyright (c) 2021 Oracle, Inc.
6-
## Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
5+
## Copyright (c) 2024 Oracle, Inc.
6+
## Licensed under the Universal Permissive License v1.0 as shown at https://oss.oracle.com/licenses/upl/
77
-->
88
<project xmlns="http://maven.apache.org/POM/4.0.0"
99
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -99,13 +99,25 @@
9999
</build>
100100

101101
<dependencies>
102-
<!-- added by peter song for database connection-->
102+
<!-- database connection dependencies -->
103103
<dependency>
104-
<groupId>com.oracle.oci.sdk</groupId>
105-
<artifactId>oci-java-sdk-common</artifactId>
106-
<version>1.32.2</version>
104+
<groupId>com.oracle.database.jdbc</groupId>
105+
<artifactId>ojdbc11</artifactId>
106+
<version>23.4.0.24.05</version>
107107
</dependency>
108-
<!-- added by peter song for database connection-->
108+
<dependency>
109+
<groupId>com.oracle.database.jdbc</groupId>
110+
<artifactId>ucp11</artifactId>
111+
<version>23.4.0.24.05</version>
112+
</dependency>
113+
<dependency>
114+
<groupId>com.oracle.database.security</groupId>
115+
<artifactId>oraclepki</artifactId>
116+
<version>23.4.0.24.05</version>
117+
</dependency>
118+
119+
120+
<!-- helidon dependencies -->
109121
<dependency>
110122
<groupId>io.helidon.webserver</groupId>
111123
<artifactId>helidon-webserver-cors</artifactId>
@@ -126,31 +138,6 @@
126138
<groupId>io.helidon.health</groupId>
127139
<artifactId>helidon-health-checks</artifactId>
128140
</dependency>
129-
<dependency>
130-
<groupId>com.oracle.ojdbc</groupId>
131-
<artifactId>ojdbc10</artifactId>
132-
<version>19.3.0.0</version>
133-
</dependency>
134-
<dependency>
135-
<groupId>com.oracle.ojdbc</groupId>
136-
<artifactId>ucp</artifactId>
137-
<version>19.3.0.0</version>
138-
</dependency>
139-
<dependency>
140-
<groupId>com.oracle.ojdbc</groupId>
141-
<artifactId>osdt_core</artifactId>
142-
<version>19.3.0.0</version>
143-
</dependency>
144-
<dependency>
145-
<groupId>com.oracle.ojdbc</groupId>
146-
<artifactId>osdt_cert</artifactId>
147-
<version>19.3.0.0</version>
148-
</dependency>
149-
<dependency>
150-
<groupId>com.oracle.ojdbc</groupId>
151-
<artifactId>oraclepki</artifactId>
152-
<version>19.3.0.0</version>
153-
</dependency>
154141
</dependencies>
155142

156143
</project>

mtdrworkshop/backend/set.sh

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,28 @@ export IMAGE_NAME=todolistapp-helidon-se
88
export IMAGE_VERSION=0.1
99

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

1515
if [ -z "$DOCKER_REGISTRY" ]; then
16-
echo "Error: DOCKER_REGISTRY env variable needs to be set!"
17-
exit 1
16+
echo "Error: DOCKER_REGISTRY env variable needs to be set!"
17+
exit 1
1818
fi
1919
if [ -z "$TODO_PDB_NAME" ]; then
20-
echo "TODO_PDB_NAME not set. Will get it with state_get"
20+
echo "TODO_PDB_NAME not set. Will get it with state_get"
2121
export TODO_PDB_NAME=$(state_get MTDR_DB_NAME)
2222
fi
2323
if [ -z "$TODO_PDB_NAME" ]; then
24-
echo "Error: TODO_PDB_NAME env variable needs to be set!"
25-
exit 1
24+
echo "Error: TODO_PDB_NAME env variable needs to be set!"
25+
exit 1
2626
fi
2727
if [ -z "$OCI_REGION" ]; then
28-
echo "OCI_REGION not set. Will get it with state_get"
29-
export OCI_REGION=$(state_get REGION)
28+
echo "OCI_REGION not set. Will get it with state_get"
29+
export OCI_REGION=$(state_get REGION)
3030
fi
3131
if [ -z "$OCI_REGION" ]; then
32-
echo "Error: OCI_REGION env variable needs to be set!"
33-
exit 1
32+
echo "Error: OCI_REGION env variable needs to be set!"
33+
exit 1
3434
fi
3535
export IMAGE=${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_VERSION}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CREATE TABLE TODOOWNER.TODOITEM (
2+
ID NUMBER GENERATED ALWAYS AS IDENTITY,
3+
DESCRIPTION VARCHAR2(4000),
4+
CREATION_TS TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
5+
DONE NUMBER(1, 0) DEFAULT 0,
6+
PRIMARY KEY (ID)
7+
);
8+
9+
INSERT INTO TODOOWNER.TODOITEM (DESCRIPTION) VALUES ('My first task!');
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
## MyToDoReact version 2.1.0
3+
##
4+
## Copyright (c) 2024 Oracle, Inc.
5+
## Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
6+
*/
7+
package com.oracle.database;
8+
9+
import io.helidon.config.Config;
10+
import oracle.ucp.jdbc.PoolDataSource;
11+
import oracle.ucp.jdbc.PoolDataSourceFactory;
12+
13+
import javax.sql.DataSource;
14+
import java.sql.Connection;
15+
import java.sql.SQLException;
16+
17+
public class AppDatasource {
18+
19+
// connection pooling using UCP
20+
private final PoolDataSource pds;
21+
private static AppDatasource instance = null;
22+
23+
// static get
24+
public synchronized static AppDatasource get(Config c) {
25+
if (instance == null) {
26+
instance = new AppDatasource(c);
27+
}
28+
return instance;
29+
}
30+
31+
// constructor, initialize datasource
32+
private AppDatasource(Config c) {
33+
this.pds = PoolDataSourceFactory.getPoolDataSource();
34+
String url = c.get("url").asString().orElse("");
35+
String username = c.get("user").asString().orElse("");
36+
String password = c.get("password").asString().orElse("");
37+
38+
try {
39+
40+
// In this application, we don't set any init, min or max size in UCP. We
41+
// also don't start the pool explicitly. This means that the very first
42+
// connection request will start the pool. The default maximum pool size
43+
// is MAX_INT which isn't appropriate and should be configured properly in
44+
// production.
45+
this.pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
46+
this.pds.setConnectionPoolName("JDBC_UCP_POOL");
47+
this.pds.setInactiveConnectionTimeout(60);
48+
this.pds.setMaxStatements(10);
49+
50+
// if provided, set
51+
if (!url.isEmpty()) {
52+
this.pds.setURL(url);
53+
}
54+
if (!username.isEmpty()) {
55+
this.pds.setUser(username);
56+
}
57+
if (!password.isEmpty()) {
58+
this.pds.setPassword(password);
59+
}
60+
61+
} catch (SQLException e) {
62+
throw new RuntimeException(e);
63+
}
64+
}
65+
66+
// retrieve connection
67+
public Connection getConnection() throws SQLException {
68+
return this.pds.getConnection();
69+
}
70+
71+
}

0 commit comments

Comments
 (0)