Prerequisite:
- Basic knowledge of Javascript and React library
- Basic knowledge of Java, SpringBoot
- Basic knowledge of MySQL
Architecture:
Tools and installation links:
- Java openjdk 17
- MySQL and MySQL Workbench
- Postman
- NodeJs, yarn
- IDE: Intellij(for Backend), VSCode(for Frontend)
Step 1: Spring Initializer
Spring Initializer is a web-based tool provided by the Spring framework that simplifies the process of creating a new Spring Boot project. It allows developers to quickly bootstrap a new Spring Boot application with the necessary dependencies and configurations.
To set up SpringBoot development environment - https://start.spring.io/
Now open the extracted zip file in Intellij
Step 2: Create packages in src main java
- model, repository, controller, exception
- The
model
represents the data of your application. In a Spring Boot application, models are typically Java classes annotated with JPA annotations that map the class properties to database columns. -
Repositories
are responsible for interacting with the database. In Spring Boot, repositories are interfaces that extend JpaRepository or CrudRepository. Spring Data JPA provides the implementation at runtime. -
Controllers
handle HTTP requests and responses. They are responsible for processing user inputs, invoking business logic, and returning the results. Controllers are typically annotated with @RestController. -
Exception
handling handles exceptions globally and provide custom error responses.
Step 3: Creating model class and connecting with MySql
Model/User:
package com.demo.fullstack_backend.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue
private long id;
private String username;
private String name;
private String email;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
// other getters and setters (use @GeneratedValue)
}
Annotations used:
@Entity: help us to map our domain objects (POJOs) to the relational database tables
@id: to designate that this member will uniquely identify the entity in the database
@GeneratedValue: On right click -> Generate getters and setters
repository/UserRepository
package com.demo.fullstack_backend.repository;
import com.demo.fullstack_backend.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> { // Long id will be used as primary key
}
Interface JpaRepository : Returns a reference to the entity with the given identifier. It contains the APIs for basic CRUD operations, the APIS for pagination, and the APIs for sorting.
Step 4: Set MySQL configurations
MySQL installation:
- Download MySQL server
- Install the server
- Add bin path in bash profile: Open the terminal
- If bash profile file is already present :
open ~/.bash_profile
else create and open the file - Add path:
export PATH=${PATH}:/usr/local/mysql-8.4.0-macos14-x86_64/bin
source ~/.bash_profile
mysql -u root -p
- Check if installation is successful:
show databases
Step 5: MySQL workbench
create database fullstack;
show databases;
use fullstack;
show tables;
desc user;
Step 6: Postmapping for sending data in database and Getmapping for getting data from databases
controller/UserController
package com.demo.fullstack_backend.controller;
import com.demo.fullstack_backend.model.User;
import com.demo.fullstack_backend.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@CrossOrigin("http://localhost:3000")
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
@PostMapping("/user")
User newUser(@RequestBody User newUser) {
return userRepository.save(newUser);
}
@GetMapping("/users")
List<User> getAllUsers() {
return userRepository.findAll();
}
}
@RestController: used for developing RESTful web services
@Autowired: allows Spring to automatically inject dependencies into the class, eliminating the need for manual configuration
@CrossOrigin: provides a way to overcome the same-origin policy applied by web browser
Step 7: Develop frontend using React and connect to springboot
- Install Node
- Install yarn
- On Terminal run:
yarn global add create-react-app
- Create and open project folder in VSCode/ any IDE and run:
create-react-app app-name
- yarn add axios (to add axios library to web application. It is a popular JavaScript library used for making HTTP requests from a web browser or Node. js)
- To use readymade material components:
- yarn add @mui/material @emotion/react @emotion/styled
- yarn add @mui/icons-material
- Add React developer tool chrome extension to inspect the React component hierarchies
- Run the application:
Backend:
Frontend:
yarn start
Good to goooo!!!
After submitting new user data:
React files: (Just 4 files ;))
App.js
import React, { useState, useEffect } from "react";
import axios from "axios";
import UserForm from "./Form/UserForm";
import UserList from "./UserList/UserList";
import "./App.css";
const App = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
loadUsers();
}, []);
const loadUsers = async () => {
const result = await axios.get("http://localhost:8080/users");
setUsers(result.data);
};
const addUser = (user) => {
setUsers([...users, user]);
};
return (
<div className="App">
<h1>Fullstack Frontend</h1>
<UserForm addUser={addUser} />
<UserList users={users} />
</div>
);
};
export default App;
App.css
.App {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
background-color: #f4f4f9;
padding: 20px;
max-width: 800px;
margin: 0 auto;
border-radius: 8px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
}
.container {
margin-top: 20px;
}
h1 {
text-align: center;
color: #333;
margin-bottom: 20px;
}
form {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
}
form div {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
color: #333;
font-weight: bold;
}
input[type="text"],
input[type="email"] {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
button {
width: 100%;
background-color: #007bff;
color: #fff;
border: none;
padding: 10px;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #0056b3;
}
ul {
list-style-type: none;
padding: 0;
}
li {
background-color: #fff;
margin-bottom: 10px;
padding: 15px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
li strong {
display: block;
color: #007bff;
}
li + li {
margin-top: 10px;
}
li div {
margin-bottom: 5px;
}
UserForm.js
import React, { useState } from "react";
import axios from "axios";
const UserForm = ({ addUser }) => {
const [user, setUser] = useState({ name: "", email: "" });
const handleChange = (e) => {
const { name, value } = e.target;
setUser({ ...user, [name]: value });
};
const handleSubmit = async (e) => {
e.preventDefault();
if (user.name && user.email) {
addUser(user);
setUser({ name: "", email: "" });
await axios.post("http://localhost:8080/user", user);
}
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>Name:</label>
<input
type="text"
name="name"
value={user.name}
onChange={handleChange}
placeholder="Enter your name"
/>
</div>
<div>
<label>Email:</label>
<input
type="email"
name="email"
value={user.email}
onChange={handleChange}
placeholder="Enter your email"
/>
</div>
<button type="submit" disabled={!(user.name && user.email)}>
Add User
</button>
</form>
);
};
export default UserForm;
UserList.js
import React from "react";
import {
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Paper,
} from "@mui/material";
const UserList = ({ users }) => {
return (
<TableContainer component={Paper} sx={{ mt: 4 }}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>ID</TableCell>
<TableCell>Name</TableCell>
<TableCell>Email</TableCell>
</TableRow>
</TableHead>
<TableBody>
{users.map((user, index) => (
<TableRow key={index}>
<TableCell>{index + 1}</TableCell>
<TableCell>{user.name}</TableCell>
<TableCell>{user.email}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
};
export default UserList;
Basic React concepts
React is a popular JavaScript library for building user interfaces, particularly single-page applications where you need a fast and interactive user experience. Here are some basic and important concepts in React:
-
Components
: Building blocks of a React application. They are self-contained and reusable pieces of UI. Types: Functional components, class components. Functional components are widely used nowadays. -
JSX
: JSX stands for JavaScript XML. It allows you to write HTML in React. -
Props
: Props (short for properties) are read-only attributes used to pass data from parent components to child components. -
State
: State is an object that represents the dynamic parts of a component and can change over time. State is managed within the component and can be updated using the setState method.
-
Lifecycle Methods
: Lifecycle methods are special methods in class components that allow you to hook into different phases of a component's life (mounting, updating, and unmounting). Examples: componentDidMount, componentDidUpdate, componentWillUnmount, etc. -
Hooks
: Hooks are functions that let you use state and other React features in functional components. Examples: useState, useEffect, useContext, etc.
-
Context
: Context provides a way to pass data through the component tree without having to pass props down manually at every level. Useful for global state like themes or user data. -
Handling Events
: Event handling in React involves defining event handlers directly in JSX, using camelCase syntax for event names (e.g., onClick), and passing functions that specify what should happen when an event occurs, ensuring a seamless interaction between user actions and the component's state or behavior. Handling events in React is similar to handling events on DOM elements. -
Rendering
: Rendering refers to the process of displaying UI elements on the screen. In React, rendering typically involves the render method, which returns a description of what you want to see on the screen in the form of a React element. -
Conditional Rendering
: It is the process of displaying elements and components based on certain conditions. Use JavaScript operators like if, &&, and ? : to create elements representing the current state. -
Lists
: In React, working with lists often involves creating a dynamic collection of elements based on data arrays. Using JavaScript methods like map, reduce, and filter allows you to manipulate and render these lists efficiently. -
Keys
: Keys help React optimize the rendering of lists by identifying each element uniquely. -
Real DOM
: The Real DOM (Document Object Model) is a programming interface provided by web browsers that allows scripts to dynamically access and update the content, structure, and style of a document. It represents the entire structure of a web page as a tree of objects, where each object represents part of the document. -
Virtual DOM
: The Virtual DOM is a lightweight representation of the real DOM. React uses it to optimize rendering by making updates in a more efficient way. When state or props change, React creates a new virtual DOM tree, compares it with the previous one (a process called "reconciliation"), and only updates the changed parts in the real DOM. -
Fragment
: Fragment allows you to group multiple elements without adding extra nodes to the DOM.
function FragmentExample() {
return (
<>
<h1>Title</h1>
<p>Description</p>
</>
);
}
Bonus Info (Error and resolution):
- If mysql server is automatically getting turned on/off: Go to System preferences/settings -> MySql => Regardless of version, invalidate the caches: a. Click File 🡒 Invalidate Caches / Restart. b. Click Invalidate and Restart.
- Error: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2): issue resolved by https://www.landfx.com/kb/installation-help/mysql/3437-mysql-stop-mac
Thanks for reading!
Top comments (4)
Great post kajal! Since this was a beginner post I would have liked more in depth explanations next time. Keep it up!
Sure Chirag !
Like right away for IntelliJ 😉
You can try using smart-doc to automatically generate postman collection, and then import it.
smart-doc-group.github.io/#/advanc...
Some comments may only be visible to logged-in visitors. Sign in to view all comments.