Skip to content

Commit 7c607ae

Browse files
sample code for ukoug workshop (#780)
* first commit Signed-off-by: Mark Nelson <mark.x.nelson@oracle.com> * source/dest version: Signed-off-by: Mark Nelson <mark.x.nelson@oracle.com> * Minor updates * Remove Eureka * DB stuff * Eureka stuff * eureka stuff * Adding loadgen scripts * typo * script update * remove sql tracing * Remove LB Stuff and added comment --------- Signed-off-by: Mark Nelson <mark.x.nelson@oracle.com> Co-authored-by: Andy Tael <andy.tael@yahoo.com>
1 parent 5e43c5d commit 7c607ae

File tree

10 files changed

+534
-0
lines changed

10 files changed

+534
-0
lines changed

ukoug/load_gen/customer.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import http from 'k6/http';
2+
import { check } from 'k6';
3+
import { randomString } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';
4+
export const options = {
5+
stages: [
6+
{ target: 3200, duration: '5m'},
7+
{ target: 4800, duration: '5m'},
8+
{ target: 9600, duration: '5m'},
9+
{ target: 0, duration: '1m'},
10+
],
11+
};
12+
13+
export default function () {
14+
const stress_endpoint = `http://localhost:8081/api/v1`;
15+
const params = {
16+
headers: {
17+
'Content-Type': 'application/json'
18+
},
19+
};
20+
// create a customer
21+
let customerResponse = createCustomer(stress_endpoint, params);
22+
check(customerResponse, {
23+
'create customer is status 201': (r) => r.status === 201
24+
});
25+
// get its customer id from response
26+
let customerId = getResponseKey(getSafePayload(customerResponse), 'customerId');
27+
if (customerId) {
28+
// get the customer by its id
29+
customerResponse = http.get(stress_endpoint + "/customer/" + customerId, params);
30+
check(customerResponse, {
31+
'GET customer is status 200': (r) => r.status === 200
32+
});
33+
if (customerResponse.status == 200) {
34+
// update and delete a customer
35+
let customerPayload = getSafePayload(customerResponse);
36+
if (customerPayload.customerId) {
37+
customerPayload.customerOtherDetails = "updated details";
38+
customerResponse = http.put(stress_endpoint + "/customer/" + customerPayload.customerId, JSON.stringify(customerPayload), params);
39+
check(customerResponse, {
40+
'UPDATE customer is status 200': (r) => r.status === 200
41+
});
42+
// delete one customer
43+
let res = http.del(stress_endpoint + "/customer/" + customerPayload.customerId,null, params);
44+
check(res, {
45+
'Delete customer is status 204': (r) => r.status === 204
46+
});
47+
}
48+
} else {
49+
console.error("get customer response is not 200",customerResponse )
50+
}
51+
} else {
52+
console.error("customer id not found", customerResponse);
53+
}
54+
}
55+
56+
function getResponseKey(obj, key) {
57+
try {
58+
return obj && obj[key] ? obj[key]: null;
59+
} catch(e) {
60+
console.error("error during parsing response", e);
61+
return null;
62+
}
63+
}
64+
65+
function createCustomer(stress_endpoint,params) {
66+
var payload = JSON.stringify({
67+
customerId: randomString(19),
68+
customerName: randomString(8),
69+
customerEmail: randomString(4) + '@oracle.com',
70+
customerPassword: 'welcome1',
71+
customerOtherDetails: randomString(20)
72+
});
73+
return http.post(stress_endpoint + "/customer", payload, params);
74+
}
75+
76+
77+
function getSafePayload(obj) {
78+
try {
79+
return obj.json();
80+
} catch (err) {
81+
return {}
82+
}
83+
}
84+
85+
export function handleSummary(data) {
86+
// add total num of req per check and % of succ
87+
let checkCounter = 0, reqCount = 0, pcntAvg = 0;
88+
if (data && data.root_group && data.root_group.checks){
89+
for (let check of data.root_group.checks){
90+
let fails = check.fails || 0;
91+
let pass = check.passes || 0;
92+
let total = fails + pass;
93+
let pcnt = (100 / total) * pass;
94+
check.percentage_of_succ = pcnt;
95+
check.totalRequests = total;
96+
checkCounter += 1;
97+
reqCount += total;
98+
pcntAvg += pcnt;
99+
}
100+
let overall_stats = {"name":"overall stats", "totalRequets": reqCount, "avgPercentageOfSuccess": (pcntAvg / checkCounter)}
101+
data.root_group.checks.push(overall_stats);
102+
}
103+
return {
104+
'summary.json': JSON.stringify(data), //the default data object
105+
};
106+
}

ukoug/load_gen/customer.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
k6 run customer.js --console-output customer.log --summary-export customer_summary.json

ukoug/pom.xml

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!-- Copyright (c) 2023, Oracle and/or its affiliates. -->
3+
<!-- Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ -->
4+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
6+
<modelVersion>4.0.0</modelVersion>
7+
8+
<parent>
9+
<groupId>org.springframework.boot</groupId>
10+
<artifactId>spring-boot-starter-parent</artifactId>
11+
<version>3.1.5</version>
12+
<relativePath/> <!-- lookup parent from repository -->
13+
</parent>
14+
15+
<groupId>com.example</groupId>
16+
<artifactId>customer</artifactId>
17+
<version>0.0.1-SNAPSHOT</version>
18+
<name>customer</name>
19+
<description>Customer Application</description>
20+
21+
<properties>
22+
<oracle-springboot-starter.version>3.1.0</oracle-springboot-starter.version>
23+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
24+
<java.version>17</java.version>
25+
<spring.boot.dependencies.version>3.1.5</spring.boot.dependencies.version>
26+
<spring-cloud.version>2022.0.4</spring-cloud.version>
27+
<maven.compiler.source>17</maven.compiler.source>
28+
<maven.compiler.target>17</maven.compiler.target>
29+
</properties>
30+
31+
<dependencies>
32+
<dependency>
33+
<groupId>org.springframework.boot</groupId>
34+
<artifactId>spring-boot-starter-data-jpa</artifactId>
35+
</dependency>
36+
<dependency>
37+
<groupId>com.oracle.database.spring</groupId>
38+
<artifactId>oracle-spring-boot-starter-ucp</artifactId>
39+
<version>${oracle-springboot-starter.version}</version>
40+
<type>pom</type>
41+
</dependency>
42+
<dependency>
43+
<groupId>com.oracle.database.spring</groupId>
44+
<artifactId>oracle-spring-boot-starter-wallet</artifactId>
45+
<version>${oracle-springboot-starter.version}</version>
46+
<type>pom</type>
47+
</dependency>
48+
<dependency>
49+
<groupId>org.springframework.boot</groupId>
50+
<artifactId>spring-boot-starter-web</artifactId>
51+
</dependency>
52+
<dependency>
53+
<groupId>org.springframework.boot</groupId>
54+
<artifactId>spring-boot-starter-actuator</artifactId>
55+
</dependency>
56+
<dependency>
57+
<groupId>io.micrometer</groupId>
58+
<artifactId>micrometer-registry-prometheus</artifactId>
59+
</dependency>
60+
<dependency>
61+
<groupId>org.springframework.cloud</groupId>
62+
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
63+
</dependency>
64+
<dependency>
65+
<groupId>org.projectlombok</groupId>
66+
<artifactId>lombok</artifactId>
67+
</dependency>
68+
</dependencies>
69+
70+
<dependencyManagement>
71+
<dependencies>
72+
<dependency>
73+
<groupId>org.springframework.boot</groupId>
74+
<artifactId>spring-boot-dependencies</artifactId>
75+
<version>${spring.boot.dependencies.version}</version>
76+
<type>pom</type>
77+
<scope>import</scope>
78+
</dependency>
79+
<dependency>
80+
<groupId>org.springframework.cloud</groupId>
81+
<artifactId>spring-cloud-dependencies</artifactId>
82+
<version>${spring-cloud.version}</version>
83+
<type>pom</type>
84+
<scope>import</scope>
85+
</dependency>
86+
</dependencies>
87+
</dependencyManagement>
88+
89+
<build>
90+
<plugins>
91+
<plugin>
92+
<groupId>org.springframework.boot</groupId>
93+
<artifactId>spring-boot-maven-plugin</artifactId>
94+
</plugin>
95+
<plugin>
96+
<groupId>org.graalvm.buildtools</groupId>
97+
<artifactId>native-maven-plugin</artifactId>
98+
</plugin>
99+
</plugins>
100+
</build>
101+
102+
</project>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) 2023, Oracle and/or its affiliates.
2+
// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
3+
4+
package com.example.customer;
5+
6+
import org.springframework.boot.SpringApplication;
7+
import org.springframework.boot.autoconfigure.SpringBootApplication;
8+
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
9+
10+
@SpringBootApplication
11+
@EnableDiscoveryClient
12+
public class CustomerApplication {
13+
14+
public static void main(String[] args) {
15+
SpringApplication.run(CustomerApplication.class, args);
16+
}
17+
18+
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
// Copyright (c) 2023, Oracle and/or its affiliates.
2+
// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
3+
4+
package com.example.customer.controller;
5+
6+
import java.util.List;
7+
import java.util.Optional;
8+
9+
import com.example.customer.model.Customers;
10+
import com.example.customer.repository.CustomersRepository;
11+
import org.springframework.http.HttpStatus;
12+
import org.springframework.http.ResponseEntity;
13+
import org.springframework.web.bind.annotation.DeleteMapping;
14+
import org.springframework.web.bind.annotation.GetMapping;
15+
import org.springframework.web.bind.annotation.PathVariable;
16+
import org.springframework.web.bind.annotation.PostMapping;
17+
import org.springframework.web.bind.annotation.PutMapping;
18+
import org.springframework.web.bind.annotation.RequestBody;
19+
import org.springframework.web.bind.annotation.RequestMapping;
20+
import org.springframework.web.bind.annotation.ResponseStatus;
21+
import org.springframework.web.bind.annotation.RestController;
22+
23+
@RestController
24+
@RequestMapping("/api/v1")
25+
public class CustomerController {
26+
final CustomersRepository customersRepository;
27+
28+
public CustomerController(CustomersRepository customersRepository) {
29+
this.customersRepository = customersRepository;
30+
}
31+
32+
@ResponseStatus(HttpStatus.OK)
33+
@GetMapping("/customer")
34+
public List<Customers> findAll() {
35+
return customersRepository.findAll();
36+
}
37+
38+
@ResponseStatus(HttpStatus.OK)
39+
@GetMapping("/customer/name/{customerName}")
40+
public List<Customers> findByCustomerByName(@PathVariable String customerName) {
41+
return customersRepository.findByCustomerNameIsContaining(customerName);
42+
}
43+
44+
45+
/**
46+
* Get Customer with specific ID.
47+
* @param id The CustomerId
48+
* @return If the customers is found, a customer and HTTP Status code.
49+
*/
50+
@GetMapping("/customer/{id}")
51+
public ResponseEntity<Customers> getCustomerById(@PathVariable("id") String id) {
52+
Optional<Customers> customerData = customersRepository.findById(id);
53+
try {
54+
return customerData.map(customers -> new ResponseEntity<>(customers, HttpStatus.OK))
55+
.orElseGet(() -> new ResponseEntity<>(HttpStatus.NOT_FOUND));
56+
} catch (Exception e) {
57+
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
58+
}
59+
}
60+
61+
/**
62+
* Get customer that contains an email.
63+
* @param email of the customer
64+
* @return Returns a customer if found
65+
*/
66+
@GetMapping("/customer/byemail/{email}")
67+
public List<Customers> getCustomerByEmail(@PathVariable("email") String email) {
68+
return customersRepository.findByCustomerEmailIsContaining(email);
69+
}
70+
71+
/**
72+
* Create a customer.
73+
* @param customer Customer object with the customer details
74+
* @return Returns a HTTP Status code
75+
*/
76+
@PostMapping("/customer")
77+
public ResponseEntity<Customers> createCustomer(@RequestBody Customers customer) {
78+
try {
79+
Customers newCustomer = customersRepository.save(new Customers(
80+
customer.getCustomerId(),
81+
customer.getCustomerName(),
82+
customer.getCustomerEmail(),
83+
customer.getCustomerOtherDetails()));
84+
return new ResponseEntity<>(newCustomer, HttpStatus.CREATED);
85+
86+
} catch (Exception e) {
87+
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
88+
}
89+
}
90+
91+
/**
92+
* Update a specific Customer (ID).
93+
* @param id The id of the customer
94+
* @param customer A customer object
95+
* @return A Http Status code
96+
*/
97+
@PutMapping("/customer/{id}")
98+
public ResponseEntity<Customers> updateCustomer(@PathVariable("id") String id, @RequestBody Customers customer) {
99+
Optional<Customers> customerData = customersRepository.findById(id);
100+
try {
101+
if (customerData.isPresent()) {
102+
Customers updCustomer = customerData.get();
103+
updCustomer.setCustomerName(customer.getCustomerName());
104+
updCustomer.setCustomerEmail(customer.getCustomerEmail());
105+
updCustomer.setCustomerOtherDetails(customer.getCustomerOtherDetails());
106+
return new ResponseEntity<>(customersRepository.save(updCustomer), HttpStatus.OK);
107+
} else {
108+
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
109+
}
110+
} catch (Exception e) {
111+
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
112+
}
113+
}
114+
115+
/**
116+
* Delete a specific customer (ID).
117+
* @param customerId the Id of the customer to be deleted
118+
* @return A Http Status code
119+
*/
120+
@DeleteMapping("/customer/{customerId}")
121+
public ResponseEntity<HttpStatus> deleteCustomer(@PathVariable("customerId") String customerId) {
122+
try {
123+
customersRepository.deleteById(customerId);
124+
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
125+
} catch (Exception e) {
126+
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
127+
}
128+
}
129+
130+
/**
131+
* Method isn't implemented.
132+
* @param amount Loan amount
133+
* @return A Http Status
134+
*/
135+
@PostMapping("/customer/applyLoan/{amount}")
136+
public ResponseEntity<HttpStatus> applyForLoan(@PathVariable ("amount") long amount) {
137+
try {
138+
// Check Credit Rating
139+
// Amount vs Rating approval?
140+
// Create Account
141+
// Update Account Balance
142+
// Notify
143+
return new ResponseEntity<>(HttpStatus.I_AM_A_TEAPOT);
144+
} catch (Exception e) {
145+
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
146+
}
147+
}
148+
}

0 commit comments

Comments
 (0)