9.14
Write a servlet and associated HTML code for the following simple application: A user is allowed to submit a form containing a number, say \(n\), and should get a response saying how many times the value \(n\) has been submitted previously. The number of times each value has been submitted previously should be stored in a database.
Python Version:
We will use the Redis database and redis-py python module.
Make sure Redis is installed on your machine :
If Redis is not installed on your machine head on over to redis.io.
Install the redis-py module:
Then install fastapi:
The following is the code of our backend:
from fastapi import FastAPI, Depends
from fastapi.middleware.cors import CORSMiddleware
import redis
= FastAPI()
app
# to learn more about the following:
# https://fastapi.tiangolo.com/tutorial/cors/
app.add_middleware(
CORSMiddleware,=["*"],
allow_origins=["GET"],
allow_methods=["*"],
allow_headers
)
# dependency with yield
# to learn more about the following:
# https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/
def get_db():
= redis.Redis(host='localhost', port=6379, db=0)
db try:
yield db
finally:
db.close()
@app.get("/submit")
def submit_a_number(n: int, db: redis.Redis = Depends(get_db)):
# if you want to learn more about INCR command of redis
# head on over to: https://redis.io/commands/incr/
return {
"freq": db.incr(n)
}
The following is taken from the documentation of redis:
What does it mean that INCR is atomic? That even multiple clients issuing INCR against the same key will never enter into a race condition. For instance, it will never happen that client 1 reads “10”, client 2 reads “10” at the same time, both increment to 11, and set the new value to 11. The final value will always be 12 and the read-increment-set operation is performed while all the other clients are not executing a command at the same time.
Start your server (note that x.py
holds the python code given above):
Use Insomnia to send requests:
Request 1: Request 2: Request 3: Request 4:
Note: The above insomnia sessions were requesting an older version of the backend app that used sqlite instead of redis. That is why you see a response time \(> 2 \text{ms}\). When using redis, response times around \(1.8 \text{ms}\) are normal. Example:
I would write the frontend with flutter and let the flutter engine compile the dart code to HTML for me.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
const MyApp());
runApp(
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {return MaterialApp(
: 'DSC Q 9.14',
title: ThemeData(
theme: Colors.blue,
primarySwatch,
): const MyHomePage(title: 'DSC Question 9.14'),
home
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
<MyHomePage> createState() => _MyHomePageState();
State
}
class _MyHomePageState extends State<MyHomePage> {
late TextEditingController tec;
String msg = "No message from server.";
@override
void initState() {
= TextEditingController();
tec super.initState();
}
@override
void dispose() {
.dispose();
tecsuper.dispose();
}
@override
Widget build(BuildContext context) {return Scaffold(
: AppBar(
appBar: Text(widget.title),
title,
): Center(
body: Column(
child: MainAxisAlignment.center,
mainAxisAlignment: <Widget>[
childrenconst Text("Enter the number you want to send: "),
TextFormField(: tec,
controller,
)
ElevatedButton(: const Text("Submit"),
child: () {
onPressedtry {
int n = int.parse(tec.text);
http.get(Uri.parse("http://127.0.0.1:8000/submit?n=$n"))
.then(
.Response r) {
(httpString body = r.body;
Map<String, dynamic> data = jsonDecode(body);
int freq = data["freq"] as int;
setState(
() {=
msg "The number $n has been submitted $freq times.";
,
}
);,
}
);catch (e) {
} .of(context).showSnackBar(const SnackBar(
ScaffoldMessenger:
content"Some error occured! that is all we know.")));
Text(
},
}),
Text(msg),
],
),
)
);
} }
Inital screen:
After submitting the number 5:
Compile:
Servlet version:
// TODO