You are on page 1of 14

Quick Guide Spring

Project CRUD
Initial Project
1. buat project spring dengan menggunakan spring initializr https://start.spring.io/
2. Pilih Spring boot (2.7.5)
3. Pilih Project, untuk management build yg akan digunakan (Pilih Maven)
4. Pilih Language, bahasa pemograman yg akan digunakan (Pilih Java)
5. Isi Informasi Project
- Group, untuk base package
- Artifact, untuk nama folder project
- Name, untuk nama dari project biasanya sama dengan Artifact
- Description, untuk deskripsi dari project
- Package name, review dari package name yg akan di generate
6. Pilih Packaging (pilih war)
- Jar, untuk aplikasi console, lib, desktop
- War, untuk aplikasi web
7. Pilih Java Version, versi java yg akan digunakan (Pilih 11)
*pilih versi lebih rendah dari versi java yg terinstall
8. Tambah Dependency isi dengan
- Spring Web, library untuk membuat aplikasi web
- Spring Boot Dev Tools, library untuk memudahkan ketika perlu merestart aplikasi ketika ada
perubahan
- Thymeleaf, library untuk UI
- Spring Data JPA, library untuk akses data ke Database
9. Klik Generate

Config file
Isi file application.properties dengan data seperti dibawah :

server.port=8081
spring.datasource.url=jdbc:mysql://localhost:3306/db_demo
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.database-platform = org.hibernate.dialect.MySQL5Dialect
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto = update
In Spring/Spring-Boot, SQL database can be initialized in different ways depending on what your
stack is.

JPA has features for DDL generation, and these can be set up to run on startup against the
database. This is controlled through two external properties:

 spring.jpa.generate-ddl (boolean) switches the feature on and off and is vendor independent.


 spring.jpa.hibernate.ddl-auto (enum) is a Hibernate feature that controls the behavior in a more
fine-grained way. See below for more detail.
Hibernate property values are: create, update, create-drop, validate and none:

 create – Hibernate first drops existing tables, then creates new tables
 update – the object model created based on the mappings (annotations or XML) is compared
with the existing schema, and then Hibernate updates the schema according to the diff. It
never deletes the existing tables or columns even if they are no more required by the
application
 create-drop – similar to create, with the addition that Hibernate will drop the database after all
operations are completed. Typically used for unit testing
 validate – Hibernate only validates whether the tables and columns exist, otherwise it throws
an exception
 none – this value effectively turns off the DDL generation
Spring Boot internally defaults this parameter value to create-drop if no schema manager has been
detected, otherwise none for all other cases.

Koneksi ke Database Mysql


Tambah dependency buat mysql connection pada pom.xml
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>

Buat Page Hello World


Buat Class Controller
@Controller
public class HelloWorldController {
@GetMapping("/hello_world")
public String hello(@RequestParam(name="name", required=false, defaultValue="World")
String name, Model model) {
model.addAttribute("name", name);
return "greeting";
}

Buat tampilan di folder template (src/main/resource/template) dengan nama file greeting.html


<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<p th:text="'Hello, ' + ${name} + '!'" />
</body>
</html>

Integrasi dengan template bootstrap


Copy asset, css, js dll ke folder static (src/main/resource/static)

Cara Deploy
1. Update main class (NamaProjectApplication.java)
Contoh :
@SpringBootApplication
public class DemoThymeleafApplication extends SpringBootServletInitializer{

public static void main(String[] args) {


SpringApplication.run(DemoThymeleafApplication.class, args);
}

@Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder builder) {
return builder.sources(DemoThymeleafApplication.class);
}
}
2. Pada pom.xml tambah code di bawah pada bagian build
<build>
<finalName>${artifactId}</finalName>

3. Buat war file, dengan menjalankan command
Mvn clean package

4. Deploy ke tomcat
Open manager gui -> deploy -> restart tomcat

Aplikasi CRUD
Referensi : https://www.baeldung.com/spring-boot-crud-thymeleaf
1. Buat package controller, model, repositories
2. Tambah anotasi ini di main class
@EnableAutoConfiguration
@ComponentScan(basePackages={"com.sample.crud"})
@EnableJpaRepositories(basePackages="com. sample.crud.repositories")
@EnableTransactionManagement
@EntityScan(basePackages="com.sample.crud.entities")
3. Buat class model
Contoh :
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;

@NotBlank(message = "Name is mandatory")


private String name;

@NotBlank(message = "Email is mandatory")


private String email;

@NotBlank(message = "Password is mandatory")


@Column(nullable = false, length = 64)
private String password;

public long getId() {


return id;
}

public void setId(long id) {


this.id = id;
}

public String getName() {


return name;
}

public void setName(String name) {


this.name = name;
}

public String getEmail() {


return email;
}

public void setEmail(String email) {


this.email = email;
}

public String getPassword() {


return password;
}

public void setPassword(String password) {


this.password = password;
}

}
Tambahkan dependency Javax.validation untuk anotasi @NotBlank
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
4. Buat Interface Repository, untuk proses crud dasar sudah di implementasikan oleh
CrudRepository
@Repository
public interface UserRepository extends CrudRepository<User, Long>{
}
5. Buat Controller
@Controller
public class UserController {
private final UserRepository userRepository;

@Autowired
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}

@GetMapping("/signup")
public String showSignUpForm(User user) {
return "add-user";
}

@PostMapping("/adduser")
public String addUser(@Valid User user, BindingResult result, Model model) {
if (result.hasErrors()) {
return "add-user";
}

userRepository.save(user);
return "redirect:/userScreen";
}

@GetMapping("/userScreen")
public String showUserList(Model model) {
model.addAttribute("users", userRepository.findAll());
return "user";
}

@GetMapping("/edit/{id}")
public String showUpdateForm(@PathVariable("id") long id, Model model) {
User user = userRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));

model.addAttribute("user", user);
return "update-user";
}

@PostMapping("/update/{id}")
public String updateUser(@PathVariable("id") long id, @Valid User user,
BindingResult result, Model model) {
if (result.hasErrors()) {
user.setId(id);
return "update-user";
}

userRepository.save(user);
return "redirect:/userScreen";
}

@GetMapping("/delete/{id}")
public String deleteUser(@PathVariable("id") long id, Model model) {
User user = userRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
userRepository.delete(user);
return "redirect:/userScreen";
}
*Tambah atribute userRepository yyg bertipe UserRepository, tambahkan juga contruktor untuk
mengisi variable userRepository dengan menggunakan @Autowired
6. Buat file view/tampilan
File add-user.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form action="#" th:action="@{/adduser}" th:object="${user}" method="post">
<label for="name">Name</label>
<input type="text" th:field="*{name}" id="name" placeholder="Name">
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
<label for="email">Email</label>
<input type="text" th:field="*{email}" id="email" placeholder="Email">
<span th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></span>
<label for="email">Password</label>
<input type="password" th:field="*{password}" id="email" placeholder="Password">
<span th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></span>

<input type="submit" value="Add User">


</form>
</body>
</html>
File update-user.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form action="#"
th:action="@{/update/{id}(id=${user.id})}"
th:object="${user}"
method="post">
<label for="name">Name</label>
<input type="text" th:field="*{name}" id="name" placeholder="Name">
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
<label for="email">Email</label>
<input type="text" th:field="*{email}" id="email" placeholder="Email">
<span th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></span>
<input type="submit" value="Update User">
</form>
</body>
</html>
File user.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<div th:switch="${users}">
<h2 th:case="null">No users yet!</h2>
<div th:case="*">
<h2>Users</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${users}">
<td th:text="${user.name}"></td>
<td th:text="${user.email}"></td>
<td><a th:href="@{/edit/{id}(id=${user.id})}">Edit</a></td>
<td><a th:href="@{/delete/{id}(id=${user.id})}">Delete</a></td>
</tr>
</tbody>
</table>
</div>
<p><a href="/signup">Add a new user</a></p>
<p><a href="/excel">download excel</a></p>
<p><a href="/pdf">download pdf</a></p>
<p><a href="/jasper">download pdf Jasper</a></p>
<p><a href="/logout">Logout</a></p>
</div>
</body>
</html>

AUTHENTIFICATION
Referensi : https://www.codejava.net/frameworks/spring-boot/user-registration-and-login-tutorial
1. Tambahkan dependency spring security
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2. Tambahkan BCryptPassword encoder ketika add user
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encodedPassword = passwordEncoder.encode(user.getPassword());
user.setPassword(encodedPassword);

3. Buat Class CustomUserDetails dengan mengimplement class UserDetails dari Spring security
public class CustomUserDetails implements UserDetails {

private User user;

public CustomUserDetails(User user) {


this.user = user;
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return null;
}

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

@Override
public String getUsername() {
// TODO Auto-generated method stub
return user.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;
}

}
4. Buat package service dan buat class dengan mengimplement UserDetailsService dari Spring
Security
public class CustomUserDetailService implements UserDetailsService {

@Autowired
private UserRepository userRepository;

@Override
public UserDetails loadUserByUsername(String username) throws
UsernameNotFoundException {
User user = userRepository.findByEmail(username);
if (user == null) {
throw new UsernameNotFoundException("User not found");
}
return new CustomUserDetails(user);
}

}
5. Buat method findByEmail di repository
@Query("SELECT u FROM User u WHERE u.email = ?1")
public User findByEmail(String email);

6. Buat package config, buat class WebSecurityConfig


@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Autowired
private DataSource dataSource;

@Bean
public UserDetailsService userDetailsService() {
return new CustomUserDetailService();
}

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

@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());

return authProvider;
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/userScreen").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login") // custom page login
.usernameParameter("email") // muse be same with login field
.defaultSuccessUrl("/userScreen")
// .failureUrl("/pages-login.html?error=true")
.permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")) // for logout
.logoutSuccessUrl("/")// url after logout success
.permitAll();
return http.build();
}

LOGGER
Referensi: https://www.baeldung.com/spring-boot-logging
1. Tambah config logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOGS" value="./logs" />

<appender name="Console"
class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg
%n%throwable
</Pattern>
</layout>
</appender>

<appender name="RollingFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOGS}/spring-boot-logger.log</file>
<encoder
class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
</encoder>

<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily and when the file reaches 10 MegaBytes -->
<fileNamePattern>${LOGS}/archived/spring-boot-logger-%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>

<!-- LOG everything at INFO level -->


<root level="info">
<appender-ref ref="RollingFile" />
<appender-ref ref="Console" />
</root>

<!-- LOG "com.example*" at TRACE level -->


<logger name="com.example" level="trace" additivity="false">
<appender-ref ref="RollingFile" />
<appender-ref ref="Console" />
</logger>

</configuration>
2. Tambah logger pada bagian yg diinginkan biasa nya pada exception
Logger logger = LoggerFactory.getLogger(LoginController.class);
logger.info("Ist Massage");

CREATE/DOWNLOAD FILE EXCEL


https://www.codejava.net/frameworks/spring-boot/export-data-to-excel-example
1. Buat package utilities, create class ExcelUtil
public class ExcelUtil {
private XSSFWorkbook workbook;
private XSSFSheet sheet;

public ExcelUtil() {
workbook = new XSSFWorkbook();
}

private void writeHeaderLine(String sheetName, String[] listColumn) {


sheet = workbook.createSheet(sheetName);

Row row = sheet.createRow(0);

CellStyle style = workbook.createCellStyle();


XSSFFont font = workbook.createFont();
font.setBold(true);
font.setFontHeight(16);
style.setFont(font);

for (int i=0; i<listColumn.length; i++) {


createCell(row, i, listColumn[i], style);
}

private void createCell(Row row, int columnCount, Object value, CellStyle style) {
sheet.autoSizeColumn(columnCount);
Cell cell = row.createCell(columnCount);
if (value instanceof Integer) {
cell.setCellValue((Integer) value);
} else if (value instanceof Boolean) {
cell.setCellValue((Boolean) value);
}else {
cell.setCellValue((String) value);
}
cell.setCellStyle(style);
}

private void writeDataLinesUser(List<User> dataUser) {


int rowCount = 1;

CellStyle style = workbook.createCellStyle();


XSSFFont font = workbook.createFont();
font.setFontHeight(14);
style.setFont(font);

for (User user : dataUser) {


Row row = sheet.createRow(rowCount++);
int columnCount = 0;

createCell(row, columnCount++, Long.toString(user.getId()), style);


createCell(row, columnCount++, user.getEmail(), style);
createCell(row, columnCount++, user.getName(), style);
}
}

public void exportUser(HttpServletResponse response, String sheetName, String[]


listColumn, List<User> dataUser) throws IOException {
writeHeaderLine(sheetName, listColumn);
writeDataLinesUser(dataUser);

ServletOutputStream outputStream = response.getOutputStream();


workbook.write(outputStream);
workbook.close();

outputStream.close();

}
}
2. Tambah dependency apache poi di pom.xml
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.0</version>
</dependency>

3. Buat method untuk mapping url ‘/excel’ di controller


@GetMapping("/excel")
public void exportToExcel(HttpServletResponse response) throws IOException {
response.setContentType("application/octet-stream");
DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
String currentDateTime = dateFormatter.format(new Date());

String headerKey = "Content-Disposition";


String headerValue = "attachment; filename=users_" + currentDateTime + ".xlsx";
response.setHeader(headerKey, headerValue);

List<User> listUsers = (List<User>) userRepository.findAll();

ExcelUtil excelExporter = new ExcelUtil();


String[] listColumn = {"Id", "Nama", "Email"};
excelExporter.exportUser(response,"Users", listColumn, listUsers);
}

CREATE/DOWNLOAD FILE PDF


https://www.codejava.net/frameworks/spring-boot/pdf-export-example
1. Buat package utilities, create class PdfUtil
public class PdfUtil {

private void writeTableHeader(PdfPTable table, String[] listColumn) {


PdfPCell cell = new PdfPCell();
cell.setBackgroundColor(Color.BLUE);
cell.setPadding(5);
Font font = FontFactory.getFont(FontFactory.HELVETICA);
font.setColor(Color.WHITE);

for(int i=0; i<listColumn.length; i++) {


cell.setPhrase(new Phrase(listColumn[i], font));
table.addCell(cell);
}

private void writeTableData(PdfPTable table, List<User> listUsers) {


for (User user : listUsers) {
table.addCell(String.valueOf(user.getId()));
table.addCell(user.getEmail());
table.addCell(user.getName());
}
}

public void exportUser(HttpServletResponse response, String[] listColumn, List<User>


listUsers) throws DocumentException, IOException {
Document document = new Document(PageSize.A4);
PdfWriter.getInstance(document, response.getOutputStream());

document.open();
Font font = FontFactory.getFont(FontFactory.HELVETICA_BOLD);
font.setSize(18);
font.setColor(Color.BLUE);

Paragraph p = new Paragraph("List of Users", font);


p.setAlignment(Paragraph.ALIGN_CENTER);

document.add(p);

PdfPTable table = new PdfPTable(3);


table.setWidthPercentage(100f);
table.setWidths(new float[] {1.5f, 3.5f, 3.0f});
table.setSpacingBefore(10);

writeTableHeader(table, listColumn);
writeTableData(table, listUsers);

document.add(table);

document.close();

}
}
2. Tambah dependency openpdf di pom.xml
<dependency>
    <groupId>com.github.librepdf</groupId>
    <artifactId>openpdf</artifactId>
    <version>1.3.8</version>
</dependency>

3. Buat method /pdf di controller


@GetMapping("/pdf")
public void exportToPDF(HttpServletResponse response) throws DocumentException,
IOException {
response.setContentType("application/pdf");
DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
String currentDateTime = dateFormatter.format(new Date());

String headerKey = "Content-Disposition";


String headerValue = "attachment; filename=users_" + currentDateTime + ".pdf";
response.setHeader(headerKey, headerValue);

List<User> listUsers = (List<User>) userRepository.findAll();

PdfUtil exporter = new PdfUtil();


String[] listColumn = {"Id", "Nama", "Email"};
exporter.exportUser(response, listColumn, listUsers);

}
PDF JasperReport
https://www.techgeeknext.com/spring-boot/spring-boot-jasper-report
1. Buat desain report dengan menggunakan jasper report studio
Untuk parameter data buat table pakai type data JBDataSourceCollection
2. Simpan file jrxml pada folder resource(src/main/resource)
3. Buat controller dan load file jrxml dan isi dengan data, kemudian generate pdf
@GetMapping("/jasper")
public void exportByJasper(HttpServletResponse response) {

try {
// create employee data
List<User> listUsers = (List<User>) userRepository.findAll();

//dynamic parameters required for report


Map<String, Object> empParams = new HashMap<String, Object>();
empParams.put("CompanyName", "List User");
empParams.put("employeeData", new JRBeanCollectionDataSource(listUsers));

JasperPrint empReport = JasperFillManager.fillReport (


JasperCompileManager.compileReport(

ResourceUtils.getFile("classpath:jasperTemplate/employees-details.jrxml")
.getAbsolutePath()) // path of the jasper report
, empParams // dynamic parameters
, new JREmptyDataSource()
);

response.setContentType("application/pdf");
DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
String currentDateTime = dateFormatter.format(new Date());
String headerKey = "Content-Disposition";

String headerValue = "attachment; filename=users_" + currentDateTime + ".pdf";


response.setHeader(headerKey, headerValue);
//create the report in PDF format

JasperExportManager.exportReportToPdfStream(empReport, response.getOutputStream());

} catch(Exception e) {
logger.error(e.toString());
}
}

Layouting
1. Buat folder fragments di folder resources/templates
2. Tambahkan code th:replace="fragments/header :: header"
Contoh:

<div th:replace="fragments/header :: header">


HEADER
</div>

Tampilan div akan diubah/direplace dengan code yang ada di file fragments/header.html
dengan id=”header”

CREATE API REST


Referensi : https://spring.io/guides/tutorials/rest/

SECURE API REST with JWT


Referensi : https://devwithus.com/spring-boot-rest-api-security-jwt/

Multiple security config : https://docs.spring.io/spring-security/site/docs/4.2.x/reference/htmlsingle/


#multiple-httpsecurity

Referensi lain : https://www.javainuse.com/spring/boot-jwt

https://www.bezkoder.com/spring-boot-jwt-authentication/ (use)

UPLOAD FILE
Referensi: https://www.bezkoder.com/spring-boot-file-upload/

https://www.baeldung.com/spring-boot-thymeleaf-image-upload

You might also like