Enotes Spring boot Project Source Code with full tutorial

Hey learners, in this post we will learn spring boot project full tutorial step by step. We will develop Enotes project using java spring boot technology. i will share your full source code with full tutorial video.

Spring Boot Project Prerequisite

In this project i will used Spring boot, Data JPA, Lambok, Hibernate, Thymeleaf, html, css and spring tool suite IDE, Mysql database using workbench .

Guys you should know this concept, if you have little bit knowledge you can follow it , i explained step by step everything you can follow video also.

Spring Boot Enotes Project Full tutorial video

Project Structure

Enotes Spring boot Project Source Code

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.6.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.enotes</groupId>
	<artifactId>SBT-Enotes</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>SBT-Enotes</name>
	<description>Enotes Spring boot Project</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		 <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		 <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>  
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		  <dependency>
			<groupId>org.thymeleaf.extras</groupId>
			<artifactId>thymeleaf-extras-springsecurity5</artifactId>
		</dependency> 

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/yt_enotes
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

SbtEnotesApplication.java

package com.enotes;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
@EnableJpaAuditing
public class SbtEnotesApplication {

	public static void main(String[] args) {
		SpringApplication.run(SbtEnotesApplication.class, args);
	}

}

CustomUserDtls.java

package com.enotes.config;

import java.util.Arrays;
import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import com.enotes.entity.UserDtls;

public class CustomUserDtls implements UserDetails {

	private UserDtls userdtls;

	public CustomUserDtls(UserDtls userdtls) {
		super();
		this.userdtls = userdtls;
	}

	public CustomUserDtls() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {

		SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(userdtls.getRole());

		return Arrays.asList(simpleGrantedAuthority);
	}

	@Override
	public String getPassword() {
		// TODO Auto-generated method stub
		return userdtls.getPassword();
	}

	@Override
	public String getUsername() {
		// TODO Auto-generated method stub
		return userdtls.getEmail();
	}

	@Override
	public boolean isAccountNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isEnabled() {
		// TODO Auto-generated method stub
		return true;
	}

}

SecurityConfig.java

package com.enotes.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Bean
	public BCryptPasswordEncoder getPasswordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Bean
	public UserDetailsService getUserDetailsService() {
		return new UserDetailsServiceImpl();
	}

	@Bean
	public DaoAuthenticationProvider getDaoAuthenticationProvider() {
		DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
		daoAuthenticationProvider.setUserDetailsService(getUserDetailsService());
		daoAuthenticationProvider.setPasswordEncoder(getPasswordEncoder());
		return daoAuthenticationProvider;
	}

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.authenticationProvider(getDaoAuthenticationProvider());
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {

		http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasRole("USER")
				.antMatchers("/**").permitAll().and().formLogin().loginPage("/login").loginProcessingUrl("/login")
				.defaultSuccessUrl("/user/addNotes").and().csrf().disable();

	}

}

UserDetailsServiceImpl.java

package com.enotes.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.enotes.entity.UserDtls;
import com.enotes.repository.UserRepository;

public class UserDetailsServiceImpl implements UserDetailsService{

	@Autowired
	private UserRepository userRepo;
	
	public UserDetailsServiceImpl() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		
		UserDtls user=userRepo.findByEmail(username);
		
		if(user==null)
		{
			throw new UsernameNotFoundException("User Not Exist");
		}else
		{
			CustomUserDtls customUserDtls =new CustomUserDtls(user);
			return customUserDtls;
		}
			
		
	}

}

HomeController.java

package com.enotes.controller;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import com.enotes.entity.UserDtls;
import com.enotes.repository.UserRepository;

@Controller
public class HomeController {
	
	
	@Autowired
	private BCryptPasswordEncoder passwordEncode;

	@Autowired
	private UserRepository userRepo;

	@GetMapping("/")
	public String home() {
		return "home";
	}

	@GetMapping("/login")
	public String login() {
		return "login";
	}

	@GetMapping("/signup")
	public String signup() {
		return "signup";
	}

	@PostMapping("/saveUser")
	public String saveUser(@ModelAttribute UserDtls user, Model m, HttpSession session) {
		
		
		user.setPassword(passwordEncode.encode(user.getPassword()));
		user.setRole("ROLE_USER");
		
		UserDtls u = userRepo.save(user);

		if (u != null) {
			session.setAttribute("msg", "Register Sucessfully");
		} else {
			session.setAttribute("msg", "Something wrong on server");
		}

		return "redirect:/signup";
	}

}

UserController.java

package com.enotes.controller;

import java.security.Principal;
import java.util.Optional;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.enotes.entity.Notes;
import com.enotes.entity.UserDtls;
import com.enotes.repository.NotesRepository;
import com.enotes.repository.UserRepository;

@Controller
@RequestMapping("/user")
public class UserController {

	@Autowired
	private UserRepository userRepository;

	@Autowired
	private NotesRepository notesRepository;

	@ModelAttribute
	public void addCommnData(Principal p, Model m) {
		String email = p.getName();
		UserDtls user = userRepository.findByEmail(email);
		m.addAttribute("user", user);
	}

	@GetMapping("/addNotes")
	public String home() {
		return "user/add_notes";
	}

	@GetMapping("/viewNotes/{page}")
	public String viewNotes(@PathVariable int page, Model m, Principal p) {

		String email = p.getName();
		UserDtls user = userRepository.findByEmail(email);

		Pageable pageable = PageRequest.of(page, 5, Sort.by("id").descending());
		Page<Notes> notes = notesRepository.findyNotesByUser(user.getId(), pageable);

		m.addAttribute("pageNo", page);
		m.addAttribute("totalPage", notes.getTotalPages());
		m.addAttribute("Notes", notes);
		m.addAttribute("totalElement", notes.getTotalElements());

		return "user/view_notes";
	}

	@GetMapping("/editNotes/{id}")
	public String editNotes(@PathVariable int id, Model m) {

		Optional<Notes> n = notesRepository.findById(id);
		if (n != null) {
			Notes notes = n.get();
			m.addAttribute("notes", notes);
		}

		return "user/edit_notes";
	}

	@PostMapping("/updateNotes")
	public String updateNotes(@ModelAttribute Notes notes, HttpSession session, Principal p) {
		String email = p.getName();
		UserDtls user = userRepository.findByEmail(email);

		notes.setUserDtls(user);

		Notes updateNotes = notesRepository.save(notes);

		if (updateNotes != null) {
			session.setAttribute("msg", "Notes Update Sucessfully");
		} else {
			session.setAttribute("msg", "Something wrong on server");
		}

		System.out.println(notes);

		return "redirect:/user/viewNotes/0";
	}

	@GetMapping("/deleteNotes/{id}")
	public String deleteNotes(@PathVariable int id,HttpSession session) {
		
		Optional<Notes> notes=notesRepository.findById(id);
		if(notes!=null)
		{
			notesRepository.delete(notes.get());
			session.setAttribute("msg", "Notes Delete Successfully");
		}
		
		return "redirect:/user/viewNotes/0";
	}

	@GetMapping("/viewProfile")
	public String viewProfile() {
		return "user/view_profile";
	}

	@PostMapping("/saveNotes")
	public String saveNotes(@ModelAttribute Notes notes, HttpSession session, Principal p) {
		String email = p.getName();
		UserDtls u = userRepository.findByEmail(email);
		notes.setUserDtls(u);

		Notes n = notesRepository.save(notes);

		if (n != null) {
			session.setAttribute("msg", "Notes Added Sucessfully");
		} else {
			session.setAttribute("msg", "Something wrong on server");
		}

		return "redirect:/user/addNotes";
	}
	
	@PostMapping("/updateUser")
	public String updateUser(@ModelAttribute UserDtls user,HttpSession session,Model m)
	{
		Optional<UserDtls> Olduser=userRepository.findById(user.getId());
		
		if(Olduser!=null)
		{
			user.setPassword(Olduser.get().getPassword());
			user.setRole(Olduser.get().getRole());
			user.setEmail(Olduser.get().getEmail());
			
			UserDtls updateUser=userRepository.save(user);
			if(updateUser!=null)
			{
				m.addAttribute("user",updateUser);
				session.setAttribute("msg", "Profile Update Sucessfully..");
			}
			
		}
		
		
		return "redirect:/user/viewProfile";
	}
	

}

Audit.java

package com.enotes.entity;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.auditing.config.AuditingConfiguration;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import lombok.Data;
import lombok.ToString;

@Data
@ToString
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class Audit {

	
	@Temporal(TemporalType.DATE)
	@CreatedDate
	@Column(name = "create_dt",nullable = false,updatable = false)
	private Date cratedDate;
	
	
	@Temporal(TemporalType.DATE)
	@LastModifiedDate
	@Column(name = "update_dt",nullable = false)
	private Date updateDate;

}

Notes.java

package com.enotes.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

import lombok.Data;

@Data
@Entity
@Table(name = "notes")
public class Notes extends Audit {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int id;
	@Column(nullable = false)
	private String title;

	@Column(nullable = false)
	private String content;

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "user_id", nullable = false)
	@OnDelete(action = OnDeleteAction.CASCADE)
	private UserDtls userDtls;

	public Notes() {
		// TODO Auto-generated constructor stub
	}

}

UserDtls.java

package com.enotes.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.Data;

@Data
@Entity
public class UserDtls {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int id;
	@Column(name = "full_name")
	private String name;
	private String email;
	private String password;
	private String about;
	private String role;

	public UserDtls() {
		// TODO Auto-generated constructor stub
	}

}

NotesRepository.java

package com.enotes.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.enotes.entity.Notes;

public interface NotesRepository extends JpaRepository<Notes, Integer>{
	
	@Query("from Notes as n where n.userDtls.id=:uid")
	Page<Notes> findyNotesByUser(@Param("uid") int uid,Pageable p);

}

UserRepository.java

package com.enotes.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.enotes.entity.UserDtls;

public interface UserRepository extends JpaRepository<UserDtls,Integer>{
	
	public UserDtls findByEmail(String email);

}

Frontend Code

style.css

.backimg {
	background: url("../img/notes.jpg");
	height: 100%;
	width: 100%;
	background-repeat: no-repeat;
	position: fixed;
	background-size: cover;
}

.navbar .nav-item .nav-link {
	font-size: 20px;
	color: white;
}

.navbar .nav-item:hover .nav-link {
	background: white;
	color: black;
	border-radius: 10px;
}

User Folder Html Code

add_notes.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
	th:replace="user/base::layout(~{::section})">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	<section>
		<div class="container-fluid p-3">
			<div class="col-md-10 offset-md-1">
				<div class="card paint-card">
					<h3 class="text-center">Add Notes</h3>
					<div th:if="${session.msg}" class="text-center" role="alert">

						<h4 class="text-success" th:text="${session.msg}"></h4>
						<th:block th:text="${#session.removeAttribute('msg')}"></th:block>
					</div>
					<div class="card-body">
						<form th:action="@{/user/saveNotes}" method="post">
							<div class="form-group">
								<label>Enter Title</label> <input type="text"
									class="form-control" name="title">
							</div>
							<div class="form-group">
								<label>Enter Description</label>
								<textarea rows="12" cols="" name="content" class="form-control"></textarea>
							</div>
							<div class="text-center">
								<button class="btn btn-primary">Submit</button>
							</div>
						</form>
					</div>
				</div>
			</div>
		</div>
	</section>
</body>
</html>

base.html

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.com"
	th:fragment="layout(content)">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport"
	content="width=device-width, initial-scale=1, shrink-to-fit=no">

<!-- Bootstrap CSS -->
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
	rel="stylesheet"
	integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
	crossorigin="anonymous">
<link rel="stylesheet"
	href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"
	integrity="sha512-Fo3rlrZj/k7ujTnHg4CGR2D7kSs0v4LLanw2qksYuRlEzO+tcaEPQogQ0KaoGN26/zrn20ImR1DfuLWnOo7aBA=="
	crossorigin="anonymous" referrerpolicy="no-referrer" />
<title>Base</title>
<link rel="stylesheet" th:href="@{/css/style.css}">
<style type="text/css">
.paint-card {
	box-shadow: 0 0 12px 0 rgba(0, 0, 0, 0.3);
}
</style>
</head>
<body>


	<!-- Start Navbar -->

	<nav class="navbar navbar-expand-lg navbar-dark bg-success">
		<div class="container-fluid">
			<a class="navbar-brand" th:href="@{/}"><i class="fas fa-book"></i>
				Enotes</a>
			<button class="navbar-toggler" type="button"
				data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
				aria-controls="navbarSupportedContent" aria-expanded="false"
				aria-label="Toggle navigation">
				<span class="navbar-toggler-icon"></span>
			</button>
			<div class="collapse navbar-collapse" id="navbarSupportedContent">
				<ul class="navbar-nav me-auto mb-2 mb-lg-0">
					<li class="nav-item"><a class="nav-link active"
						aria-current="page" th:href="@{/user/addNotes}"> Add Notes</a></li>

					<li class="nav-item"><a class="nav-link active"
						aria-current="page" th:href="@{/user/viewNotes/0}">View Notes</a></li>

				</ul>
				<form class="d-flex">
					<a th:href="@{/user/viewProfile}" class="btn btn-light"><i
						class="fas fa-user-circle"></i> [[${user.name}]]</a> 
						
						<a th:href="@{/logout}"
						class="btn btn-light ms-2"><i class="fas fa-sign-in-alt"></i>
						Logout</a>
				</form>
			</div>
		</div>
	</nav>

	<!--End Navbar  -->

	<div th:replace="${content}"></div>


	<!-- Optional JavaScript -->
	<!-- jQuery first, then Popper.js, then Bootstrap JS -->
	<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
		integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
		crossorigin="anonymous"></script>
	
	<script
		src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
		integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
		crossorigin="anonymous"></script>
	
	<script
		src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
		integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
		crossorigin="anonymous">
	
	</script>

</body>
</html>

edit_notes.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
	th:replace="user/base::layout(~{::section})">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<section>
		<div class="container-fluid p-3">
			<div class="col-md-10 offset-md-1">
				<div class="card paint-card">
					<h3 class="text-center">Edit Notes</h3>
					<!-- <div th:if="${session.message}"
						th:classappend="${session.message.type}" class="text-center"
						role="alert">

						<h4 th:text="${session.message.content}"></h4>
						<th:block th:text="${#session.removeAttribute('message')}"></th:block>
					</div> -->
					<div class="card-body">
						<form th:action="@{/user/updateNotes}"  method="post">
							<div class="form-group">
								<label>Enter Title</label> <input type="text" th:value="${notes.title}"
									class="form-control" name="title">
							</div>
							<div class="form-group">
								<label>Enter Description</label>
								<textarea rows="12" cols="" name="content" th:value="${notes.content}"
									class="form-control">[[${notes.content}]]</textarea>
							</div>
							<input type="hidden" th:value="${notes.id}" name="id">
							
							<div class="text-center">
								<button class="btn btn-primary">Update</button>
							</div>
						</form>
					</div>
				</div>
			</div>
		</div>
	</section>
</body>
</html>

view_notes.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
	th:replace="user/base::layout(~{::section})">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	<section>
		<div class="container">
			<h3 class="text-center">Notes</h3>
			 <div th:if="${session.msg}"
				 class="text-center"
				role="alert">

				<h4 th:text="${session.msg}"></h4>
				<th:block th:text="${#session.removeAttribute('msg')}"></th:block>
			</div> 

			<div class="col-md-12 mt-3" th:each="n:${Notes}">
				<div class="card paint-card">
					<div class="card-body">
						<div class="text-center">
							<img alt="" th:src="@{/img/paper.png}"
								style="width: 50px; height: 50px;">
						</div>

						<h5>[[${n.title}]]</h5>
						<p>
							[[${n.content}]] <br> <br> <span class="font-weight-bold">Upload
								Date :</span> [[${n.updateDate}]]

						</p>
						<div class="text-center">
							<a th:href="@{'/user/editNotes/'+${n.id}}" class="btn btn-primary btn-sm">Edit</a>
							
							 <a
								th:href="@{'/user/deleteNotes/'+${n.id}}" class="btn btn-danger btn-sm ml-2">Delete</a>
						</div>
					</div>
				</div>
			</div>




			<div class="row p-4">
				<div class="col-md-4">Total Elements : [[${totalElement}]]</div>
				<div class="col-md-6">
					<nav aria-label="Page navigation example">
						<ul class="pagination">
							
							<li th:classappend="${pageNo==0} ? 'disabled':'' " class="page-item">
							<a class="page-link" th:href="@{'/user/viewNotes/'+${pageNo-1} }"
							
								aria-label="Previous"> <span aria-hidden="true">&laquo;</span>
							</a>
							
							</li>
							
							
							<li th:each="i:${#numbers.sequence(1,totalPage)}" th:classappend="${pageNo+1==i}?'active':''" class="page-item">
							
							<a th:href="@{'/user/viewNotes/' +${i-1} }" class="page-link" href="#">[[${i}]]</a>
							
							</li>
							
							<li th:classapppend="${pageNo+1==totalPage} ? 'disabled' :  '' " class="page-item">
							<a class="page-link" th:href="@{'/user/viewNotes/'+${pageNo+1}}"
								aria-label="Next"> <span aria-hidden="true">&raquo;</span>
							</a>
							</li>
							
						</ul>
					</nav>
				</div>
			</div>





		</div>

	</section>
</body>
</html>

view_profile.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
	th:replace="user/base::layout(~{::section})">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

	<section>
		<div class="container p-5">
			<div class="row">
				<div class="col-md-4">
					<div class="card paint-card">
						<div class="card-body">
							<form th:action="@{/saveUser}" method="post">

								<p class="fs-4 text-center">View Profile</p>

								<div class="form-group mt-2">
									<label> Name</label> <input type="text" name="name"
										th:value="${user.name}" readonly class="form-control"
										required="required">

								</div>

								<div class="form-group mt-2">
									<label> Email</label> <input type="email" name="email"
										th:value="${user.email}" readonly class="form-control"
										required="required">
								</div>

								<div class="form-group mt-2">
									<textarea rows="3" cols="" class="form-control" name="about"
										th:value="${user.about}" readonly placeholder="Enter About">[[${user.about}]]</textarea>
								</div>



							</form>
						</div>
					</div>
				</div>

				<div class="col-md-6">
					<div class="card paint-card">
						<div class="card-body">
							<form th:action="@{/user/updateUser}" method="post">

								<p class="fs-4 text-center">Edit Profile</p>
								<div th:if="${session.msg}" class="text-center" role="alert">

									<h4 class="text-success" th:text="${session.msg}"></h4>
									<th:block th:text="${#session.removeAttribute('msg')}"></th:block>
								</div>

								<div class="form-group mt-2">
									<label>Enter Name</label> <input type="text" name="name"
										th:value="${user.name}" class="form-control"
										required="required">

								</div>

								<div class="form-group mt-2">
									<label>Enter Email</label> <input type="email" name="email"
										th:value="${user.email}" readonly class="form-control"
										required="required">
								</div>


								<div class="form-group mt-2">
									<textarea rows="3" cols="" class="form-control" name="about"
										placeholder="Enter About">[[${user.about}]]</textarea>
								</div>
								<input type="hidden" name="id" th:value="${user.id}">


								<div class="text-center mt-3">
									<button class="btn bg-primary text-white">Update</button>
									<button type="reset" class="btn btn-primary text-white">Reset</button>
								</div>




							</form>
						</div>
					</div>
				</div>



			</div>
		</div>
	</section>
</body>
</html>

Outside User Folder html Code

base.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.com"
	th:fragment="layout(content)">
<head>
<meta charset="ISO-8859-1">
<title>Base Page</title>
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
	rel="stylesheet"
	integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
	crossorigin="anonymous">

<link rel="stylesheet"
	href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"
	integrity="sha512-Fo3rlrZj/k7ujTnHg4CGR2D7kSs0v4LLanw2qksYuRlEzO+tcaEPQogQ0KaoGN26/zrn20ImR1DfuLWnOo7aBA=="
	crossorigin="anonymous" referrerpolicy="no-referrer" />

<link rel="stylesheet" th:href="@{/css/style.css}">
<style type="text/css">
.paint-card {
	box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.3);
}
</style>
</head>
<body>

	<!-- Start Navbar -->

	<nav class="navbar navbar-expand-lg navbar-dark bg-success">
		<div class="container-fluid">
			<a class="navbar-brand" th:href="@{/}"><i class="fas fa-book"></i> Enotes</a>
			<button class="navbar-toggler" type="button"
				data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
				aria-controls="navbarSupportedContent" aria-expanded="false"
				aria-label="Toggle navigation">
				<span class="navbar-toggler-icon"></span>
			</button>
			<div class="collapse navbar-collapse" id="navbarSupportedContent">
				<ul class="navbar-nav me-auto mb-2 mb-lg-0">
					<li class="nav-item"><a class="nav-link active"
						aria-current="page" th:href="@{/}"><i class="fas fa-home"></i> Home</a></li>

				</ul>
				<form class="d-flex">
					<a th:href="@{login}" class="btn btn-light"><i class="fas fa-sign-in-alt"></i> Login</a> <a
						th:href="@{signup}" class="btn btn-light ms-2"><i class="fas fa-user-plus"></i> Signup</a>
				</form>
			</div>
		</div>
	</nav>

	<!--End Navabar  -->

	<div th:replace="${content}"></div>




	<script
		src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
		integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
		crossorigin="anonymous"></script>
</body>
</html>

home.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
	th:replace="base::layout(~{::section})">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>



</head>
<body>
	<section>
	
		<div class="backimg">
			<div class="text-white text-center">
				<h1>ENotes- Save Notes</h1>
				<p>Start Collecting your Notes in very smarter way .We provied
					very difficult and smarter way of handling Notes</p>
				<button class="btn bg-primary text-white">Get Start</button>
			</div>
		</div>

	</section>


	
</body>
</html>

login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
	th:replace="base::layout(~{::section})">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	<section>
		<div class="container  p-5">
			<div class="row">
				<div class="col-md-6 offset-md-3">
					<div class="card paint-card">
						<div class="card-body">
							<h4 class="form-signin-heading text-center">Sign in</h4>
							<form class="form-signin" method="post" th:action="@{/login}">

 
								 <div th:if="${param.error}" class="alert alert-danger">
									Invalid username & Password</div>

								<div th:if="${param.logout}" class="alert alert-success">
									Logout Sucessfully</div> 

								<div class="form-group">
									<label>Email</label> <input type="text" id="username"
										name="username" class="form-control" required autofocus>
								</div>
								<div class="form-group mt-2">
									<label>Password</label> <input type="password" id="password"
										name="password" class="form-control" required>
								</div>
								<button class="btn btn-primary col-md-12 mt-3" type="submit">Sign
									in</button>

								<div class="text-center">
									<a href="/signup">Create Account</a>
								</div>
							</form>
						</div>
					</div>
				</div>
			</div>
		</div>
	</section>

</body>
</html>

signup.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
	th:replace="base::layout(~{::section})">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	<section>
		<div class="container">
			<div class="row">
				<div class="col-md-6 offset-md-3">
					<div class="card mt-2 paint-card">
						<h1 class="text-center">Register Here</h1>

						<!--alert message  -->
						 <div th:if="${session.msg}"
							class="text-center">

							<h4 class="text-success" th:text="${session.msg}"></h4>
							<th:block th:text="${#session.removeAttribute('msg')}"></th:block>
						</div> 

						<!--alert message  -->

						<div class="card-body">
							<form th:action="@{/saveUser}" method="post">



								<div class="form-group mt-2">
									<label>Enter Name</label> <input type="text" name="name"
										class="form-control" required="required">

								</div>

								<div class="form-group mt-2">
									<label>Enter Email</label> <input type="email" name="email"
										class="form-control" required="required">
								</div>

								<div class="form-group mt-2">
									<label>Enter Password</label> <input type="password"
										name="password" class="form-control" required="required">
								</div>

								<div class="form-group mt-2">
									<textarea rows="3" cols="" class="form-control" name="about"
										placeholder="Enter About"></textarea>
								</div>



								<div class="text-center mt-3">
									<button class="btn bg-primary text-white">Submit</button>
									<button type="reset" class="btn btn-primary text-white">Reset</button>
								</div>




							</form>
						</div>
					</div>

				</div>
			</div>
		</div>
	</section>
</body>
</html>

2 thoughts on “Enotes Spring boot Project Source Code with full tutorial”

Leave a Comment