initial
This commit is contained in:
commit
74ae93a96e
10 changed files with 94691 additions and 0 deletions
|
|
@ -0,0 +1,239 @@
|
|||
Coding 1 (Autowire and Dependency Injection)
|
||||
|
||||
- Once starter project is ready its time to do some other stuff
|
||||
- Create POJO (Plain old java object)
|
||||
In `com/example/demo` where there is java file create another file containing classA `classA.java`
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
@Component
|
||||
public class ClassA {
|
||||
private int aid;
|
||||
private String aname;
|
||||
private String tech;
|
||||
|
||||
public int getAid() {
|
||||
return aid;
|
||||
}
|
||||
|
||||
public String getAname() {
|
||||
return aname;
|
||||
}
|
||||
|
||||
public String getTech() {
|
||||
return tech;
|
||||
}
|
||||
|
||||
public void setAid(int aid) {
|
||||
this.aid = aid;
|
||||
}
|
||||
|
||||
public void setAname(String aname) {
|
||||
this.aname = aname;
|
||||
}
|
||||
|
||||
public void setTech(String tech) {
|
||||
this.tech = tech;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
- Now linking POJO with demo without DI
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
@SpringBootApplication
|
||||
public class DemoApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
ConfigurableApplicationContext context= SpringApplication.run(DemoApplication.class, args);
|
||||
|
||||
|
||||
|
||||
ClassA a = new ClassA();
|
||||
|
||||
a.show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
- Now linking POJO with DI.
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
@SpringBootApplication
|
||||
public class DemoApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
ConfigurableApplicationContext context= SpringApplication.run(DemoApplication.class, args);
|
||||
|
||||
|
||||
ClassA a = context.getBean(ClassA.class);
|
||||
|
||||
|
||||
a.show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
- Theory : SpringApplication.run will create a spring container and it will contain objects also called spring bean. When spring bean are created we have 2 different scopes in spring core(base version without any web, jdbc,etc) ie Singleton and Prototype. Singleton is the default one. Whenever a container is created object of class with @Component annotation will be created too. if we want them to be created manually then use Prototype scope. Advantage of protoptype is that multiple objects can be created while in singleton same object is returned everytime.
|
||||
- Add the scope prototype like this
|
||||
in `ClassA.java`
|
||||
```java
|
||||
@Component
|
||||
@Scope(value="prototype")
|
||||
public class ClassA {
|
||||
private int aid;
|
||||
private String aname;
|
||||
private String tech;
|
||||
|
||||
public ClassA(){
|
||||
super();
|
||||
System.out.println("Class A object created");
|
||||
}
|
||||
|
||||
public int getAid() {
|
||||
return aid;
|
||||
}
|
||||
//....
|
||||
```
|
||||
In `DemoApplication.java`
|
||||
```java
|
||||
ClassA a = context.getBean(ClassA.class);
|
||||
a.show();
|
||||
ClassA a1 = context.getBean(ClassA.class);
|
||||
a1.show();
|
||||
```
|
||||
- Create another POJO named Laptop
|
||||
in `Laptop.java`
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class Laptop {
|
||||
private int lid;
|
||||
private String brand;
|
||||
|
||||
public String getBrand() {
|
||||
return brand;
|
||||
}
|
||||
|
||||
public int getLid() {
|
||||
return lid;
|
||||
}
|
||||
|
||||
public void setBrand(String brand) {
|
||||
this.brand = brand;
|
||||
}
|
||||
|
||||
public void setLid(int lid) {
|
||||
this.lid = lid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// TODO Auto-generated method stub
|
||||
// return super.toString();
|
||||
|
||||
return "Laptop[lid="+lid+", brand="+brand+ "]";
|
||||
}
|
||||
|
||||
public void compile(){
|
||||
System.out.println("Compiling");
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
In `ClassA.java`
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
// @Scope(value="prototype")
|
||||
public class ClassA {
|
||||
private int aid;
|
||||
private String aname;
|
||||
private String tech;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("laptop")
|
||||
private Laptop laptop;
|
||||
|
||||
public ClassA(){
|
||||
super();
|
||||
System.out.println("Class A object created");
|
||||
}
|
||||
|
||||
public int getAid() {
|
||||
return aid;
|
||||
}
|
||||
|
||||
public String getAname() {
|
||||
return aname;
|
||||
}
|
||||
|
||||
public String getTech() {
|
||||
return tech;
|
||||
}
|
||||
|
||||
public void setAid(int aid) {
|
||||
this.aid = aid;
|
||||
}
|
||||
|
||||
public void setAname(String aname) {
|
||||
this.aname = aname;
|
||||
}
|
||||
|
||||
public void setTech(String tech) {
|
||||
this.tech = tech;
|
||||
}
|
||||
|
||||
public Laptop getLaptop() {
|
||||
return laptop;
|
||||
}
|
||||
|
||||
public void setLaptop(Laptop laptop) {
|
||||
this.laptop = laptop;
|
||||
}
|
||||
|
||||
public void show()
|
||||
{
|
||||
System.out.println("in show");
|
||||
laptop.compile();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
- As ClassA is using object of Laptop class means it is dependent on Laptop class so Autowired annotation is used to link with bean of object type `Laptop.class`. If we want to link with object name then we have to use Qualifier annotation and provide name in string form inside parenthesis. By default object name is class name with all the character as lower case and in this case it will be `laptop`. it doesnt depend on name of instance created at ClassA. In order to give custom object name
|
||||
In `Laptop.java`
|
||||
```java
|
||||
@Component("lap")
|
||||
public class Laptop {
|
||||
```
|
||||
and in `ClassA.java`
|
||||
```java
|
||||
@Autowired
|
||||
@Qualifier("lap")
|
||||
private Laptop lapto;
|
||||
```
|
||||
|
|
@ -0,0 +1,346 @@
|
|||
Coding 2 (Web app with Spring boot)
|
||||
|
||||
- Advantage of spring boot is embeded tomcat means we dont have to download tomcat externally so its easy to deploy it too.
|
||||
- Create `HomeController.java` in com.example.demo
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Controller
|
||||
public class HomeController {
|
||||
|
||||
@RequestMapping("home")
|
||||
@ResponseBody
|
||||
public String home(){
|
||||
System.out.println("hi");
|
||||
return "hi";
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
ResponseBody annotation means some data is being returned instead of some file. above can be replaced by simply using RestController annotation instead of Controller and we dont need to include ResponseBody
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class HomeController {
|
||||
|
||||
@RequestMapping("home")
|
||||
public String home(){
|
||||
System.out.println("hi");
|
||||
return "hi";
|
||||
}
|
||||
}
|
||||
|
||||
````
|
||||
- To return a file say html file or image file put them at `src/main/resources/static` folder and return filename
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Controller
|
||||
public class HomeController {
|
||||
|
||||
@RequestMapping("home")
|
||||
public String home(){
|
||||
System.out.println("home");
|
||||
return "home.html";
|
||||
}
|
||||
|
||||
@RequestMapping("image")
|
||||
public String image(){
|
||||
System.out.println("image");
|
||||
return "image.png";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
**Application properties files**
|
||||
- Spring boot has auto configure thing which does configuration for us but we can modify it too by editing the file `application.properties` at `src/main/resources`
|
||||
- In `static` folder if we want to group them in some other folder like pages then we have to do this
|
||||
in `application.properties`
|
||||
```
|
||||
spring.application.name=demo
|
||||
spring.mvc.view.prefix=/pages/
|
||||
```
|
||||
We can have include
|
||||
`spring.mvc.view.suffix=.jsp` too but this is for jsp only and not for simple html
|
||||
- above will make changes globally for all routes so instead of using prefix we can simply do this when returning file `return "pages/home.html";`
|
||||
|
||||
|
||||
## Accepting client data
|
||||
https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-requestmapping.html
|
||||
|
||||
- for returning files : https://www.geeksforgeeks.org/returning-an-image-or-a-file-with-spring/
|
||||
- In the below code there are 3 different examples for handling/parsing query strings and returning json or string
|
||||
- handling request and response servlet way : using write method of res and getParameter of req
|
||||
- handling response and request spring way
|
||||
: using `ResponseEntity<T>` and `RequestEntity<T>`
|
||||
- handling query parameter spring way : using `RequestParam` annotation
|
||||
- catching custom parameters : enclosing variable in curly braces in RequestMapping annotation and capturing it with PathVariable annotation
|
||||
- returning back files : using Path and UrlResource classes
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@Controller
|
||||
public class HomeController {
|
||||
|
||||
@RequestMapping("home")
|
||||
// @ResponseBody
|
||||
public void home(HttpServletRequest req, HttpServletResponse res) throws IOException{
|
||||
|
||||
// handling request and response servlet way
|
||||
|
||||
// localhost:8080/home?name=<name>
|
||||
String name = req.getParameter("name");
|
||||
|
||||
// String json = "{\"name\" : \"homepage\"}";
|
||||
String json = String.format("{\"name\" : \"%s\"}", name);
|
||||
|
||||
System.out.println("home "+name);
|
||||
|
||||
res.setContentType("application/json");
|
||||
|
||||
PrintWriter out= res.getWriter();
|
||||
out.write(json);
|
||||
out.flush();
|
||||
|
||||
|
||||
// return "pages/home.html";
|
||||
// return "{\"name\" : \"homepage\"}";
|
||||
}
|
||||
|
||||
@RequestMapping("image")
|
||||
public String image(){
|
||||
System.out.println("image");
|
||||
return "image.png";
|
||||
}
|
||||
|
||||
@RequestMapping("json-data")
|
||||
public ResponseEntity<String> getJSON( RequestEntity<String> req) throws IOException{
|
||||
// handling response and request spring way
|
||||
|
||||
URI url = req.getUrl();
|
||||
|
||||
|
||||
|
||||
|
||||
// to get query string params like name=<name>&id=<id>
|
||||
String queryString=url.getQuery();
|
||||
|
||||
|
||||
|
||||
// String json = "{\"name\" : \"homepage\"}";
|
||||
String json = String.format("{\"queryString\" : \"%s\"}", queryString);
|
||||
|
||||
System.out.println("home "+queryString);
|
||||
|
||||
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(json);
|
||||
|
||||
}
|
||||
|
||||
// handling query parameter spring way
|
||||
@RequestMapping("query-param")
|
||||
@ResponseBody
|
||||
public String getQueryParam( @RequestParam("name") String name, @RequestParam("id") String id){
|
||||
System.out.println("name: "+name);
|
||||
return "name="+name+" id="+id;
|
||||
}
|
||||
|
||||
@RequestMapping("{itemid}")
|
||||
@ResponseBody
|
||||
public String getItemID(@PathVariable String itemid){
|
||||
System.out.println("itemid="+itemid);
|
||||
return itemid;
|
||||
}
|
||||
|
||||
@RequestMapping("file")
|
||||
public ResponseEntity<Resource> getFile() throws IOException{
|
||||
Path path = Paths.get("src/main/resources/static/image.png");
|
||||
|
||||
// Loading resource
|
||||
Resource resource =(Resource) new UrlResource(path.toUri());
|
||||
|
||||
return ResponseEntity.ok().contentType(MediaType.IMAGE_PNG).body(resource);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Model and View
|
||||
- ModelAndView is Holder for both Model and View in the web MVC framework
|
||||
- For understanding thymeleaf refer to this
|
||||
https://www.baeldung.com/thymeleaf-in-spring-mvc
|
||||
https://www.baeldung.com/java-thymeleaf-expression-types
|
||||
- Make sure thymeleaf is installed first. Add this dependency under dependencies section in `pom.xml`
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
- in thymeleaf to be some special tag attributes like `th:text` (for simple text) , `th:utext` (for nested HTML )
|
||||
in `HomeController.java`
|
||||
```java
|
||||
@RequestMapping("model-view")
|
||||
public ModelAndView modelview(@RequestParam("name") String myname){
|
||||
ModelAndView mv = new ModelAndView();
|
||||
mv.addObject("name", myname);
|
||||
|
||||
// refers to thyme.html
|
||||
mv.setViewName("thyme");
|
||||
|
||||
return mv;
|
||||
}
|
||||
```
|
||||
in `src/main/resources/templates/thyme.html`
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<style>
|
||||
.red{
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="greeting" th:text="${name}"></h1>
|
||||
<span th:utext="'my <span class=\'red\'>name ' +${name}+ '</span> is ' + ${name}"></span>
|
||||
<h1 class="greeting" th:text="${name}"></h1>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
```
|
||||
at `http://localhost:8080/model-view?name=ipsum`
|
||||

|
||||
|
||||
|
||||
### Model
|
||||
- Instead of using RequestParam annotation to get query parameters we can simply create a POJO and pass pojo object as parameter in controller method. When we map it to route and when that route sends data to it then it will recieve it as object so with appropriate class object in parameter it is possible to read those query parameters.
|
||||
in `Alien.java`
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
public class Alien {
|
||||
private int aid;
|
||||
private String aname;
|
||||
private String lang;
|
||||
|
||||
public int getAid() {
|
||||
return aid;
|
||||
}
|
||||
|
||||
public String getAname() {
|
||||
return aname;
|
||||
}
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setAid(int aid) {
|
||||
this.aid = aid;
|
||||
}
|
||||
|
||||
public void setAname(String aname) {
|
||||
this.aname = aname;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In `HomeController.java`
|
||||
```java
|
||||
@RequestMapping("model")
|
||||
public ModelAndView model(Alien alien)
|
||||
{
|
||||
|
||||
ModelAndView mv = new ModelAndView();
|
||||
mv.addObject("obj", alien);
|
||||
|
||||
mv.setViewName("thyme");
|
||||
|
||||
return mv;
|
||||
}
|
||||
```
|
||||
or we can use Model class too
|
||||
```java
|
||||
@RequestMapping("model")
|
||||
public String model(Alien alien, Model model)
|
||||
{
|
||||
|
||||
model.addAttribute("obj", alien);
|
||||
|
||||
return "thyme";
|
||||
}
|
||||
```
|
||||
in `thyme.html`
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<style>
|
||||
.red{
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="greeting" th:text="${obj.aname}"></h1>
|
||||
<span th:utext="'my <span class=\'red\'>name ' +${obj.aid}+ '</span> is ' + ${obj.aname}"></span>
|
||||
<h1 class="greeting" th:text="'My lang is '+${obj.lang}"></h1>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
```
|
||||
at `http://localhost:8080/model?aname=telusko&aid=101&lang=java`
|
||||

|
||||
|
||||
## Services
|
||||
- Instead of having all logic in controllers we can create separate service beans . @Component, @Service. these annotations all control beans but for readbility we prefer Service when actually creating service
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
Coding 3 (Spring REST)
|
||||
- Before diving into this some terminology and concepts
|
||||
- JDBC (Java Database Connectivity) : It is an API that is inbuilt in java for connecting to database
|
||||
- JPA (Java Persistent API) : It is ORM (Object Relational Mapping) . Useful to directly work with java objects instead of SQL statements. It maps java objects properties to respective fields of table of relatioal database.
|
||||
- JDBCTemplate : Internally use JDBC and eliminate problem with JDBC and make code more clear and concise. Enables us to directly write SQL queries.This is related to Spring boot
|
||||
- MySQL Connector/J (JDBC driver) : It is a JDBC Type 4 driver, which means that it is pure Java implementation of the MySQL protocol and does not rely on the MySQL client . This is required to use mysql in spring boot
|
||||
There is MySQL Connector/Java too but it is provided by third party and isnt official one
|
||||
- references : https://spring.io/guides/gs/relational-data-access
|
||||
https://spring.io/guides/gs/accessing-data-mysql
|
||||
https://www.geeksforgeeks.org/how-to-execute-multiple-sql-commands-on-a-database-simultaneously-in-jdbc/ (normal jdbc not jdbctemplate)
|
||||
https://mkyong.com/spring/spring-jdbctemplate-batchupdate-example/ (for batchupdate)
|
||||
- Java concepts
|
||||
- Anonymous inner class : A class with no name for which single object is created. Useful to create a new object without needing to create a subclass with overloading/overriding methods. To explain this lets simplify it to its normal form step by step
|
||||
Eg:
|
||||
Anonymous inner class
|
||||
```java
|
||||
new BatchPreparedStatementSetter() {
|
||||
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
ps.setString(1, books.get(i).getName());
|
||||
ps.setBigDecimal(2, books.get(i).getPrice());
|
||||
}
|
||||
|
||||
public int getBatchSize() {
|
||||
return books.size();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
inner class
|
||||
```java
|
||||
BatchPreparedStatementSetter setter = new BatchPreparedStatementSetter() {
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
// Implementation of setting values for the prepared statement
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
// Implementation of batch size
|
||||
}
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
a proper class
|
||||
```java
|
||||
|
||||
// here BatchPreparedStatmentSetter in interface not class thats why implements is used not extends
|
||||
public class BookBatchPreparedStatementSetter implements BatchPreparedStatementSetter {
|
||||
|
||||
private final List<Book> books;
|
||||
|
||||
public BookBatchPreparedStatementSetter(List<Book> books) {
|
||||
this.books = books;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
ps.setString(1, books.get(i).getName());
|
||||
ps.setBigDecimal(2, books.get(i).getPrice());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return books.size();
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
- In the following code few things like
|
||||
- Dependencies that are to be installed are `spring-web`, `jdbc-api` and `mysql-connector-j`.
|
||||
- A separate class is used for this which will act as a bean called `DataLoader`.
|
||||
- Object of `JdbcTemplate` class can be created with DI through Autowired annotation.
|
||||
- execute method is used to perform sql query. By default only single query is allowed. to allow multiple queries `spring.datasource.url` must contain query parameter as `allowMultiQueries=true`.
|
||||
- There are other methods like `update`, `query`, `queryForList`, `batchUpdate` which accept 2nd/3rd parameter after sql query(1st para) and they support placeholder ie `?` for sql queries.
|
||||
- update method is for operations like insert,update,etc. query is for select, queryForList will return the records without need for manually mapping them. batchupdate is used to insert/update multiple records at once. same can be done with update too as it accepts array too but multiple placeholders needed to be added too and code would not be readable.
|
||||
in `application.properties`
|
||||
```yml
|
||||
spring.application.name=demo
|
||||
spring.datasource.url=jdbc:mysql://localhost:3306/test?allowMultiQueries=true
|
||||
spring.datasource.username=root
|
||||
spring.datasource.password=<password>
|
||||
```
|
||||
|
||||
Add following under dependencies section
|
||||
in `pom.xml`
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>9.0.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
in `DataLoader.java`
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
class Name{
|
||||
|
||||
public int id;
|
||||
public String name;
|
||||
|
||||
Name(int id,String name){
|
||||
this.id=id;
|
||||
this.name=name;
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
public class DataLoader {
|
||||
|
||||
@Autowired
|
||||
JdbcTemplate jdbcTemplate;
|
||||
|
||||
public void execute() throws Exception{
|
||||
// jdbcTemplate.execute ("drop table if exists customers");
|
||||
// jdbcTemplate.execute("create table customers(" + "id serial, name varchar(255))");
|
||||
|
||||
jdbcTemplate.execute("drop table if exists customers; create table customers(id serial, name varchar(255));");
|
||||
|
||||
jdbcTemplate.execute( String.format("INSERT INTO customers values (%d, '%s')", 1, "hey2"));
|
||||
jdbcTemplate.update("INSERT INTO customers values (?, ?)", 3, "hey3");
|
||||
|
||||
Object[] args = new Object[] {2, "y"};
|
||||
jdbcTemplate.update("INSERT INTO customers values (?, ?)",args);
|
||||
|
||||
List<Name> names= new ArrayList<>();
|
||||
names.add(new Name(4,"hey4" ));
|
||||
names.add(new Name(5,"hey5" ));
|
||||
names.add(new Name(6,"hey6" ));
|
||||
names.add(new Name(7,"hey7" ));
|
||||
|
||||
jdbcTemplate.batchUpdate("INSERT INTO customers values (?, ?)", new BatchPreparedStatementSetter() {
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException{
|
||||
ps.setInt(1, names.get(i).id);
|
||||
ps.setString(2, names.get(i).name);
|
||||
}
|
||||
|
||||
public int getBatchSize(){
|
||||
return names.size();
|
||||
}
|
||||
});
|
||||
|
||||
Object[] args2= new Object[]{"2"};
|
||||
List<String> lis= jdbcTemplate.query("select name from customers where id=?", new RowMapper<String>() {
|
||||
@Override
|
||||
public String mapRow(ResultSet rs, int rowNum) throws SQLException{
|
||||
return rs.getString("name");
|
||||
}
|
||||
},args2);
|
||||
|
||||
List<Map<String,Object>> lis2= jdbcTemplate.query("select * from customers", new RowMapper<Map<String,Object>>(){
|
||||
@Override
|
||||
public Map<String,Object> mapRow(ResultSet rs, int rowNum) throws SQLException{
|
||||
|
||||
Map<String,Object> row = new HashMap<>();
|
||||
int coln=rs.getMetaData().getColumnCount();
|
||||
|
||||
for(int i=1;i<= coln;i++){
|
||||
String colname = rs.getMetaData().getColumnName(i);
|
||||
Object colvalue = rs.getObject(i);
|
||||
row.put(colname,colvalue);
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
List<Map<String,Object>> lis3 = jdbcTemplate.queryForList("select * from customers");
|
||||
|
||||
System.out.println("lis3: "+lis3.toString());
|
||||
|
||||
|
||||
|
||||
|
||||
for(int i=0; i< lis.size();i++){
|
||||
System.out.println(i+": "+lis.get(i));
|
||||
}
|
||||
|
||||
System.out.println("lis2: "+lis2.toString());
|
||||
|
||||
for( Map<String,Object> map : lis2 ){
|
||||
Set<String> keys = map.keySet();
|
||||
keys.forEach(key -> {
|
||||
System.out.println(key+": "+map.get(key));
|
||||
|
||||
});
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
in `DemoApplication.java`
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
@SpringBootApplication
|
||||
public class DemoApplication {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ConfigurableApplicationContext context =SpringApplication.run(DemoApplication.class, args);
|
||||
|
||||
DataLoader dl= context.getBean(DataLoader.class);
|
||||
dl.execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,473 @@
|
|||
Coding 4 (Spring REST telusko)
|
||||
- Creating a sample form which will send data to controller and controller will store it in database
|
||||
- Added a get method to return records when id is given as request so a new view is added too
|
||||
|
||||
Creating POJO class at `src/main/com/example/demo/model`
|
||||
```java
|
||||
package com.example.demo.model;
|
||||
|
||||
public class Alien {
|
||||
private int aid;
|
||||
private String aname;
|
||||
|
||||
public int getAid() {
|
||||
return aid;
|
||||
}
|
||||
|
||||
public void setAid(int aid) {
|
||||
this.aid = aid;
|
||||
}
|
||||
|
||||
public String getAname() {
|
||||
return aname;
|
||||
}
|
||||
|
||||
public void setAname(String aname) {
|
||||
this.aname = aname;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// TODO Auto-generated method stub
|
||||
return String.format("Alien [aid=%d] [aname=%s]",aid,aname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
Alien alien = (Alien) obj;
|
||||
|
||||
// for String or any non primitive type like Integer,Long,etc its necessary to check using equals method as by default
|
||||
// == will check equality of reference not their value
|
||||
if( alien.getAid()==this.aid && this.aname.equals(alien.getAname()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Creating a view `home.html` at `src/main/resources/templates`
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<form action="addAlien">
|
||||
<input type="text" name="aid"><br>
|
||||
<input type="text" name="aname"><br>
|
||||
<input type="submit"><br>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Creating a view `showAlien.html` at `src/main/resources/templates`
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<h3 th:text="${alien}"></h3>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Creating a class to handle database operations named `TableLoader` at `src/main/com/example/demo/model`
|
||||
```java
|
||||
package com.example.demo.model;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
@Component
|
||||
public class TableLoader {
|
||||
|
||||
final String TableName="alien";
|
||||
|
||||
@Autowired
|
||||
JdbcTemplate jdbcTemplate;
|
||||
|
||||
public void createTable(){
|
||||
jdbcTemplate.execute(String.format("drop table if exists %s; create table alien (AID serial, ANAME text)",TableName));
|
||||
|
||||
}
|
||||
|
||||
public void fillInitialData(){
|
||||
jdbcTemplate.update("insert into alien (ANAME) values (?)", "navin");
|
||||
}
|
||||
|
||||
public void insertData(Alien alien){
|
||||
jdbcTemplate.update("insert into alien (ANAME) values (?)", alien.getAname());
|
||||
}
|
||||
|
||||
public Alien findById(int aid){
|
||||
|
||||
|
||||
|
||||
List<Alien> resList = jdbcTemplate.query("select * from alien where AID=?", new RowMapper<Alien>() {
|
||||
@Override
|
||||
public Alien mapRow(ResultSet rs, int rowNum) throws SQLException{
|
||||
|
||||
Alien alien= new Alien();
|
||||
alien.setAid(rs.getInt("AID"));
|
||||
alien.setAname(rs.getString("ANAME"));
|
||||
|
||||
return alien;
|
||||
}
|
||||
},aid);
|
||||
|
||||
return resList.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Creating controller `AlienController`
|
||||
```java
|
||||
package com.example.demo.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import com.example.demo.model.Alien;
|
||||
import com.example.demo.model.TableLoader;
|
||||
|
||||
@Controller
|
||||
public class AlienController {
|
||||
|
||||
@Autowired
|
||||
TableLoader tl;
|
||||
|
||||
@RequestMapping("/")
|
||||
public String home(){
|
||||
return "home";
|
||||
}
|
||||
|
||||
@RequestMapping("/addAlien")
|
||||
public String addAlien(Alien alien){
|
||||
tl.insertData(alien);
|
||||
return "home";
|
||||
}
|
||||
|
||||
@RequestMapping("/getAlien")
|
||||
public ModelAndView getAlien(@RequestParam int aid){
|
||||
ModelAndView mv= new ModelAndView("showAlien");
|
||||
|
||||
Alien alien = tl.findById(aid);
|
||||
|
||||
System.out.println("Alien: "+alien.toString());
|
||||
|
||||
mv.addObject(alien);
|
||||
return mv;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Finally our spring boot app class
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
import com.example.demo.model.TableLoader;
|
||||
|
||||
@SpringBootApplication
|
||||
public class DemoApplication {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ConfigurableApplicationContext context =SpringApplication.run(DemoApplication.class, args);
|
||||
|
||||
TableLoader tl= context.getBean(TableLoader.class);
|
||||
tl.createTable();
|
||||
tl.fillInitialData();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
- Optimizing findById method
|
||||
- Create a separate class called `AlienRowMapper` which implments RowMapper interface and override mapRow method to map it to Alien class object (ResultSet -> Alien )
|
||||
```java
|
||||
package com.example.demo.model;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
public class AlienRowMapper implements RowMapper<Alien>{
|
||||
|
||||
@Override
|
||||
public Alien mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
|
||||
Alien alien = new Alien();
|
||||
alien.setAid(rs.getInt("AID"));
|
||||
alien.setAname(rs.getString("ANAME"));
|
||||
|
||||
return alien;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
Modify method
|
||||
```java
|
||||
public Alien findById(int aid){
|
||||
Alien alien = jdbcTemplate.queryForObject("select * from alien where AID=?", new AlienRowMapper(),aid);
|
||||
|
||||
return alien;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### GET methods
|
||||
- Make sure to use either GetMapping or include GET in method parameter of RequestMapping to prevent conflict between same path but of different method requests
|
||||
in `AlienController`
|
||||
```java
|
||||
// get methods
|
||||
@RequestMapping("/aliens")
|
||||
@ResponseBody
|
||||
public String getAliens(){
|
||||
return tl.findAll().toString();
|
||||
}
|
||||
|
||||
@RequestMapping(path="/alien/{aid}",method = RequestMethod.GET,produces = {"application/json"})
|
||||
@ResponseBody
|
||||
public String getAlienByParam(@PathVariable("aid") int aid){
|
||||
return tl.findById(aid).toString();
|
||||
}
|
||||
```
|
||||
|
||||
in `TableLoader`
|
||||
```java
|
||||
public List<Alien> findAll(){
|
||||
return jdbcTemplate.query("select * from alien",new AlienRowMapper());
|
||||
}
|
||||
```
|
||||
- optional class : https://www.javatpoint.com/java-8-optional
|
||||
- spring boot have jackson-core class to handle java objects by converting them to json when passed as response
|
||||
- in `AlienController`
|
||||
```java
|
||||
@RequestMapping("/getAlien")
|
||||
public ModelAndView getAlien(@RequestParam int aid){
|
||||
ModelAndView mv= new ModelAndView("showAlien");
|
||||
|
||||
Optional<Alien> alienOption = tl.findById(aid);
|
||||
|
||||
Alien alien=alienOption.get();
|
||||
|
||||
System.out.println("Alien: "+alien.toString());
|
||||
|
||||
mv.addObject(alien);
|
||||
return mv;
|
||||
}
|
||||
|
||||
// get methods
|
||||
@RequestMapping("/aliens")
|
||||
@ResponseBody
|
||||
public List<Alien> getAliens(){
|
||||
return tl.findAll();
|
||||
}
|
||||
|
||||
// with Optional container if there is no object to be returned is null then it will handle that too
|
||||
@RequestMapping("/alien/{aid}")
|
||||
@ResponseBody
|
||||
public Optional<Alien> getAlienByParam(@PathVariable("aid") int aid){
|
||||
return tl.findById(aid);
|
||||
}
|
||||
```
|
||||
in `TableLoader`
|
||||
```java
|
||||
|
||||
public Optional<Alien> findById(int aid){
|
||||
Alien alien = jdbcTemplate.queryForObject("select * from alien where AID=?", new AlienRowMapper(),aid);
|
||||
|
||||
return Optional.ofNullable(alien);
|
||||
}
|
||||
```
|
||||
|
||||
### Content Negotiation
|
||||
- To tell server or client what type of content needs to be sent or accepted
|
||||
- jackson-core handle json but not xml so if accept type for response is xml then another package ie jackson dataformat xml need to be installed too. so add following in `pom.xml`
|
||||
```xml
|
||||
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-xml</artifactId>
|
||||
<version>2.17.2</version>
|
||||
</dependency>
|
||||
|
||||
```
|
||||
- at server side if we wanna give a response of particular content type so that it is restricted to that only(if client wants json and restriction at server is xml then it will fail).
|
||||
When passing muliple arguments inside anootation we need to mention argument field too like path,produces,etc
|
||||
- in `AlienController`
|
||||
```java
|
||||
// this is also possible
|
||||
// @RequestMapping(path="/aliens",produces = {"application/xml","application/json"})
|
||||
@RequestMapping(path="/aliens",produces = {"application/xml"})
|
||||
@ResponseBody
|
||||
public List<Alien> getAliens(){
|
||||
return tl.findAll();
|
||||
}
|
||||
```
|
||||
so now u will have this when u try json
|
||||

|
||||
|
||||
## POST Request
|
||||
- for accepting post requests change that to `RequestMethod.POST`
|
||||
in `AlienController`
|
||||
```java
|
||||
@RequestMapping(path="/alien",consumes = "multipart/form-data", produces = "application/json",method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public Alien addAlienPOST(Alien alien){
|
||||
tl.insertData(alien);
|
||||
return alien;
|
||||
}
|
||||
```
|
||||
for `RequestMapping(path="path1", method=RequestMethod.POST)` there is a shorthand form ie `PostMapping("path1")`
|
||||
- `multipart/form-data` content is not raw body so whenever we send raw data like json/xml we need to use annotation RequestBody otherwise no value will be catched to instance of alien object
|
||||
in `AlienController`
|
||||
```java
|
||||
@PostMapping("/alien")
|
||||
@ResponseBody
|
||||
public Alien addAlienPOST(@RequestBody Alien alien){
|
||||
tl.insertData(alien);
|
||||
return alien;
|
||||
}
|
||||
```
|
||||
|
||||
### PUT and DELETE
|
||||
- in the following code apprach for put is to save and update means if there is no resource found to be updated then insert operation will take place and new id will be generated and returned
|
||||
- In order to get the new generated idm object of KeyHolder class needs to be used and pass in update method of jdbctemplate appropiately.
|
||||
- in update method, preparedstatement way (ie overloading) is to be used.
|
||||
- findById needs to be modified to use query instead of queryforobject in order to not deal with emptyresultSet exception
|
||||
|
||||
in `TableLoader`
|
||||
```java
|
||||
public Optional<Alien> findById(int aid){
|
||||
List<Alien> results = jdbcTemplate.query(
|
||||
"SELECT * FROM alien WHERE AID = ?",
|
||||
new AlienRowMapper(),
|
||||
aid
|
||||
);
|
||||
|
||||
return results.stream().findFirst();
|
||||
}
|
||||
|
||||
public void deleteById(int aid){
|
||||
jdbcTemplate.update("delete from alien where AID=?", aid);
|
||||
}
|
||||
|
||||
public Alien saveOrUpdateData(Alien alien,int aid){
|
||||
// System.out.println("starting of saveorupdate");
|
||||
Optional<Alien> a= this.findById(aid);
|
||||
// System.out.println("before if");
|
||||
if(!a.isPresent()){
|
||||
// System.out.println("starting of if");
|
||||
String insertSQL= "insert into alien (ANAME) values (?)" ;
|
||||
KeyHolder keyHolder= new GeneratedKeyHolder();
|
||||
|
||||
// System.out.println("Before inserting");
|
||||
// jdbcTemplate.update(insertSQL, alien.getAname(),keyHolder,"AID");
|
||||
jdbcTemplate.update(connection->{
|
||||
PreparedStatement ps=connection.prepareStatement(insertSQL, new String[] {"AID"});
|
||||
ps.setString(1,alien.getAname());
|
||||
return ps;
|
||||
},keyHolder);
|
||||
// System.out.println("after inserting");
|
||||
Number generatedID = keyHolder.getKey();
|
||||
System.out.println("after getting key: "+generatedID.intValue());
|
||||
return this.findById(generatedID.intValue()).get();
|
||||
|
||||
|
||||
|
||||
}
|
||||
else{
|
||||
jdbcTemplate.update("update alien set ANAME=? where AID=?", alien.getAname(),aid);
|
||||
return this.findById(aid).get();
|
||||
}
|
||||
}
|
||||
```
|
||||
in `AlienController`
|
||||
```java
|
||||
@DeleteMapping("/alien/{aid}")
|
||||
@ResponseBody
|
||||
public Alien deleteAlien(@PathVariable int aid){
|
||||
Alien a = tl.findById(aid).get();
|
||||
tl.deleteById(aid);
|
||||
return a;
|
||||
}
|
||||
|
||||
@PutMapping("/alien/{aid}")
|
||||
@ResponseBody
|
||||
public Alien updateAlien(@RequestBody Alien alien, @PathVariable("aid") int aid){
|
||||
Alien a=tl.saveOrUpdateData(alien,aid);
|
||||
return a;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Spring Data REST
|
||||
Note : it requires spring data jpa as it is built on top of that
|
||||
- A way to create REST without controller or spring-web dependency.
|
||||
- First we will need `rest repositories` dependency so add this in `pom.xml` and install
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-rest</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
- we need to use annotation `RepositoryRestResource`
|
||||
syntax is
|
||||
`@RepositoryRestResource(collectionResourceRel="<base_url>",path="<path>")`
|
||||
- this will map the paths with jpaRepository functions so need to make a separate rest controller.
|
||||
- collectionResourceRel paramater is responsible for generating self and other resource links in response body
|
||||
in `AlienRepo`
|
||||
```java
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springgramework.data.rest.core.annotation.RepositoryRestResource;
|
||||
|
||||
@RepositoryRestResource(collectionResourceRel="aliens",path="aliens")
|
||||
public interface AlienRepo extends JpaRepository<Alien,Integer> {
|
||||
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
```
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
Coding 5 (Sprint Boot Testing)
|
||||
https://www.youtube.com/watch?v=kbr5RaRDgQk&list=PLS1QulWo1RIZ5Vy1lyTlfjqtbut9BijN9
|
||||
|
||||
- We need mockito and junit runner to test our api and repository so add following in `pom.xml`
|
||||
```xml
|
||||
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-runner -->
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-runner</artifactId>
|
||||
<version>1.11.0-M2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>5.12.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
```
|
||||
|
||||
- In the following code, some things to be mentioned
|
||||
- Mock annotation will mark field as mock and InjectMock will mark a field where injection has to be performed
|
||||
- Separate List of records ie objects of Alien class has been created which will be used as repo which is to be expcted later
|
||||
- `Before` annotation methods are being used to setup objects or initializing things before testing
|
||||
- when method of mockito will expect a result in this case list of records when findAll method is used of repo
|
||||
- mockmvc instance is used to mimic controller and its perform method will mimic requests like GET in this case and later it is checking json after checking length of list of records and checking a random ie third record name here
|
||||
|
||||
in `src/test/java/AlienController.java`
|
||||
```java
|
||||
package com.example.demo.controller;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
import static org.hamcrest.Matchers.hasSize; // Import for hasSize
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
// import org.assertj.core.internal.Arrays;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.example.demo.model.Alien;
|
||||
import com.example.demo.model.TableLoader;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.ObjectWriter;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AlienControllerTest {
|
||||
private MockMvc mockMvc;
|
||||
|
||||
ObjectMapper objMapper = new ObjectMapper();
|
||||
ObjectWriter objwriter= objMapper.writer();
|
||||
|
||||
@Mock
|
||||
private TableLoader tLoader;
|
||||
|
||||
@InjectMocks
|
||||
private AlienController aController;
|
||||
|
||||
Alien alien1 = new Alien(101, "name101");
|
||||
Alien alien2 = new Alien(102, "name102");
|
||||
Alien alien3 = new Alien(103, "name103");
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Before
|
||||
public void setUp(){
|
||||
// initializes object with mock and injectmocks annotation
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
// builds mockmvc instance for Controller annotation objects
|
||||
this.mockMvc=MockMvcBuilders.standaloneSetup(aController).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAliens() throws Exception{
|
||||
|
||||
|
||||
|
||||
List<Alien> aliens= new ArrayList<>(Arrays.asList(alien1,alien2,alien3));
|
||||
|
||||
Mockito.when(tLoader.findAll()).thenReturn(aliens);
|
||||
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/aliens").
|
||||
contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$", hasSize(3)) )
|
||||
.andExpect(jsonPath("$[2].aname",is("name103") ));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAlienByParam() throws Exception {
|
||||
|
||||
Mockito.when(tLoader.findById(alien1.getAid())).thenReturn(Optional.ofNullable(alien1));
|
||||
|
||||
MockHttpServletRequestBuilder mockRequest = MockMvcRequestBuilders.get("/alien/101")
|
||||
.contentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
mockMvc.perform(mockRequest).andExpect(status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$", notNullValue()) )
|
||||
// ;
|
||||
.andExpect(jsonPath("$.aname",is("name101") ));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
### POST Request Testing
|
||||
```java
|
||||
@Test
|
||||
public void testAddAlien() throws Exception{
|
||||
Alien alien = new Alien(101,"hey1");
|
||||
|
||||
// as insertAlien method of tlLoader s void so no result is expected thats why no when method is used
|
||||
|
||||
// converting object 'alien' to json
|
||||
String alienJSON = objwriter.writeValueAsString(alien);
|
||||
|
||||
MockHttpServletRequestBuilder mockRequest = MockMvcRequestBuilders.post("/alien")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.content(alienJSON);
|
||||
|
||||
mockMvc.perform(mockRequest).andExpect(status().isOk())
|
||||
.andExpect( jsonPath("$", notNullValue()))
|
||||
.andExpect(jsonPath("$.aname", is("hey1")));
|
||||
```
|
||||
|
||||
|
||||
### PUT Request Testing
|
||||
- when method use equals method to check result so if equals method is not overriden in POJO(Alien class here) then implement it
|
||||
- With use of when we can initialize some data too for testing. so if we r checking findByID is returning the record then it means after it checks with mockmvc request , its mock version is implemented too. Without using when if we try to update then it will be treated as new record not updating old one
|
||||
```java
|
||||
@Test
|
||||
public void testUpdateAlien() throws Exception {
|
||||
|
||||
// to check if equals method is working properly or not
|
||||
Alien updatedAlien = new Alien(101,"heyo1");
|
||||
String alienJSONTemp = objMapper.writeValueAsString(updatedAlien);
|
||||
Alien updatedAlien2 = objMapper.readValue(alienJSONTemp, Alien.class);
|
||||
assertEquals(updatedAlien, updatedAlien2);
|
||||
|
||||
|
||||
Alien alien = new Alien(101, "heyo1");
|
||||
|
||||
Mockito.when(tLoader.findById(alien1.getAid())).thenReturn(Optional.of(alien1));
|
||||
Mockito.when(tLoader.saveOrUpdateData(Mockito.eq(alien), Mockito.eq(101))).thenReturn(alien);
|
||||
|
||||
String alienJSON = objwriter.writeValueAsString(alien);
|
||||
|
||||
MockHttpServletRequestBuilder mockRequest = MockMvcRequestBuilders.put("/aliens/101")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.content(alienJSON);
|
||||
|
||||
ResultActions ra =mockMvc.perform(mockRequest).andExpect(status().isOk())
|
||||
.andExpect( jsonPath("$", notNullValue()))
|
||||
.andExpect(jsonPath("$.aname", is("heyo1")));
|
||||
|
||||
|
||||
// printing response json
|
||||
String responseJSON = ra.andReturn().getResponse().getContentAsString();
|
||||
System.out.println("resjson: "+responseJSON);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Delete request test
|
||||
```java
|
||||
@Test
|
||||
public void testDeleteAlien() throws Exception {
|
||||
|
||||
|
||||
|
||||
Mockito.when(tLoader.findById(alien1.getAid())).thenReturn(Optional.of(alien1));
|
||||
// Mockito.when(tLoader.deleteById(alien1.getAid())).thenReturn(alien1);
|
||||
|
||||
MockHttpServletRequestBuilder mockRequest = MockMvcRequestBuilders.delete("/alien/101")
|
||||
.contentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
ResultActions ra = mockMvc.perform(mockRequest).andExpect(status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$", notNullValue()) )
|
||||
// ;
|
||||
.andExpect(jsonPath("$.aname",is("name101") ));
|
||||
|
||||
// printing response json
|
||||
String responseJSON = ra.andReturn().getResponse().getContentAsString();
|
||||
System.out.println("resjson: "+responseJSON);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
Extras telusko
|
||||
|
||||
- for configuring h2 database(in memory database)
|
||||
- make sure package is there in pom.xml
|
||||
- add following in `application.properties`
|
||||
```yml
|
||||
spring.h2.console.enabled=true
|
||||
spring.datasource.platform=h2
|
||||
spring.datasource.url=jdbc:h2:mem:telusko
|
||||
```
|
||||
here telusko is name of database
|
||||
- now start your application and go to `localhost:8080/h2~console` and u will get a login page. now click on test connection button
|
||||
- for configuring JPA
|
||||
- make sure respective dependency is there and at `application.properties` along with spring.datasource properties one more is mentioned for say mysql
|
||||
`spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect`
|
||||
- in POJO add annotation `Entity` above class defintion and in instance say `aid` add `@Id` annotation
|
||||
- now a table with fields of those POJO instance name will be created
|
||||
- u can add `data.sql` in `src/main/resources` to add initial data
|
||||
- in order to do crud operations use CrudRepository which is a part of spring data commons which is part of JPA
|
||||
- Create this interface
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
public interface AlienRepo extends CrudRepository<Other,Integer> {
|
||||
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
and then in your main file/controller to save data use
|
||||
```java
|
||||
public class HomeController(){
|
||||
@Autowire
|
||||
Alienrepo repo;
|
||||
|
||||
@RequestMapping("/addAlien")
|
||||
public String addAlien(Alien alien){
|
||||
repo.save(alien);
|
||||
return "home";
|
||||
}
|
||||
|
||||
@RequestMapping("/getAlien")
|
||||
public ModelAndView getAlien(@RequestParam int aid){
|
||||
ModelAndView mv= new ModelAndView("showAlien");
|
||||
Alien alien=repo.findById(aid).orElse(new Alien());
|
||||
mv.addObject(alien);
|
||||
return mv;
|
||||
}
|
||||
}
|
||||
```
|
||||
- More query methods for interface Repo
|
||||
- In the following code, these other query methods are defined by just declaring then by following certain conventions like `findBy<PropertyName><Operation>` here property like Tech,Aid(first letter must be capital and other as small)
|
||||
- everything is not configured with conventions so for complex queries `Query` annotation have to be used. `?1` is used instead of `?` bcz there can be other placeholders too and its to index them.
|
||||
```java
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
public interface AlienRepo extends CrudRepository<Other,Integer> {
|
||||
|
||||
List<Alien> findByTech(String tech);
|
||||
|
||||
List<Alien> findByAidGreaterThan(int aid);
|
||||
|
||||
// jpql instead of sql
|
||||
@Query("from Alien where tech=?1 order by aname")
|
||||
List<Alien> findByTechSorted(String tech);
|
||||
}
|
||||
```
|
||||
122
joplin notion extension/Web Development/Java/Spring/Extras.md
Normal file
122
joplin notion extension/Web Development/Java/Spring/Extras.md
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
Extras
|
||||
- parsing json using jackson
|
||||
https://mkyong.com/java/jackson-how-to-parse-json/
|
||||
[How to parse JSON string with Jackson - Mkyong.com.pdf](../../../../_resources/How%20to%20parse%20JSON%20string%20with%20Jackson%20-%20Mkyong.com.pdf)
|
||||
[How to parse JSON string with Jackson - Mkyong.com (22_9_2024 8_29_12 am).html](../../../../_resources/How%20to%20parse%20JSON%20string%20with%20Jackson%20-%20Mkyong.com.html)
|
||||
|
||||
|
||||
|
||||
|
||||
```java
|
||||
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.json.*;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
public class DemoApplication {
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception{
|
||||
SpringApplication.run(DemoApplication.class, args);
|
||||
ObjectMapper objectMapper= new ObjectMapper();
|
||||
JsonNode obj=objectMapper.readTree("[\"java is oops\", \"java is not oops\", \"java is annoying\"]");
|
||||
if(obj.isArray()){
|
||||
for(int i=0;i<obj.size();i++){
|
||||
System.out.println(obj.get(i).asText());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
```
|
||||
- for json array to `List<String>`
|
||||
```java
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
List<String> options= objmapper.readValue(q.getOptions(), objmapper.getTypeFactory().constructCollectionType(List.class, String.class));
|
||||
```
|
||||
- spring cors
|
||||
https://spring.io/guides/gs/rest-service-cors
|
||||
```java
|
||||
package com.example.restservicecors;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class GreetingController {
|
||||
|
||||
private static final String template = "Hello, %s!";
|
||||
|
||||
private final AtomicLong counter = new AtomicLong();
|
||||
@CrossOrigin(origins = "http://localhost:9000")
|
||||
@GetMapping("/greeting")
|
||||
public Greeting greeting(@RequestParam(required = false, defaultValue = "World") String name) {
|
||||
System.out.println("==== get greeting ====");
|
||||
return new Greeting(counter.incrementAndGet(), String.format(template, name));
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Array.map equivalent in java
|
||||
```java
|
||||
List<Integer> correctOptions = questionsResponses.stream().map(questionsResponse-> questionsResponse.getCorrectOptionNumber()).toList();
|
||||
```
|
||||
- converting biginteger into int
|
||||
`int questionID = ((BigInteger) questionResponseMap.get("questionID")).intValue();`
|
||||
- when using dependency
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
by default it adds authentication layer for accessing rest api, if that is not needed then it can be disabled by adding following bean
|
||||
```java
|
||||
package com.example.demo; // Adjust the package name as needed
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().permitAll() // Allow all requests
|
||||
.and()
|
||||
.csrf().disable(); // Optionally disable CSRF protection
|
||||
|
||||
return http.build();
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
- configure PORT
|
||||
https://www.baeldung.com/spring-boot-change-port
|
||||
in application.properties
|
||||
`server.PORT=8081`
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
Getting started
|
||||
|
||||
|
||||
**Dependency injection**
|
||||
https://www.youtube.com/watch?v=J1f5b4vcxCQ : Dependeny injection, the best pattern
|
||||
|
||||
Dependency
|
||||
- there r functions or objects that use other objects or functions and they r called dependency. There are 2 types of coupling.
|
||||
1. Hard coupling: Here dependency cant be changed
|
||||
2. Loose coupling: To change dependency in future
|
||||
|
||||
|
||||
Dependency injection
|
||||
- Instead of instantiating new code in constructor or function in same braces/scope we pass it instead through parameter to be used.
|
||||
- Main goal of dependency injection is to achieve loose coupling.
|
||||
eg
|
||||
without DI(Dependency Injection)
|
||||
```java
|
||||
public class Laptop{
|
||||
HardDrive obj1 = new HitachiHD();
|
||||
}
|
||||
```
|
||||
with DI
|
||||
```java
|
||||
public class Laptop{
|
||||
HardDrive obj1;
|
||||
Laptop(HardDrive obj){
|
||||
this.obj1= obj;
|
||||
}
|
||||
}
|
||||
```
|
||||
- It is possible using external service. That service is responsible for creating objects.
|
||||
- Example in spring boot
|
||||
```java
|
||||
class Laptop{
|
||||
@Autowired
|
||||
HardDrive obj1;
|
||||
}
|
||||
|
||||
@Component
|
||||
class HitachiHD implements HardDrive{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
With this `@Autorired` annotation it will find the component which is tagged by `@Component` to connect to it.
|
||||
- Not only this is useful to prevent tight coupling, but also for testing.
|
||||
When we wanna test laptop
|
||||
then we may not need to check harddrive bcz it is already tested so with these we can separate it too. We can create *mock object* of the class if it is loosely coupled.
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
Initializing project
|
||||
https://docs.spring.io/spring-boot/tutorial/first-application/index.html
|
||||
|
||||
Download maven repos from https://mvnrepository.com/
|
||||
|
||||
1. First make sure that java and maven are installed. Gradle can be used too but maven is preferred for simplicity. check it by `java -version` and `mvn -v`.
|
||||
2. Like react have `package.json` which contains structure and what is to be installed so in spring boot it is `pom.xml`. pom stands for project object model. This is pom.xml for starter.
|
||||
```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>
|
||||
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>myproject</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
|
||||
<parent>
|
||||
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.3.3</version>
|
||||
</parent>
|
||||
|
||||
<!-- Additional lines to be added here... -->
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
```
|
||||
3. Then in the root folder type `mvn package` in terminal to download related maven and spring plugins. its like `npm install` of react. This will download dependencies on `~/.m2/repository`
|
||||
4. Create `src/main/java/MyApplication.java` and type following
|
||||
```java
|
||||
// may recieve an error if not under custom package
|
||||
package com.myapp
|
||||
|
||||
// these will be added when starting app for first time
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
// controller as C in MVC
|
||||
@RestController
|
||||
@SpringBootApplication
|
||||
public class MyApplication {
|
||||
|
||||
// map to root directory
|
||||
@RequestMapping("/")
|
||||
String home() {
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// running spring application
|
||||
SpringApplication.run(MyApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
5. Run `mvn spring-boot:run` in terminal to run app.
|
||||
6. Finally create an executeable jar to able to distribute it as it we need to package spring and maven plugins and packages into single jar file. All they need is java installed to run it . Add following after dependencies section in `pom.xml`
|
||||
```xml
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
```
|
||||
7. Then type `mvn package` to create the build (executable jar) in target folder.
|
||||
8. In order to run this jar file type `java -jar target/myproject-0.0.1-SNAPSHOT.jar`. In order to peek in this jar file use
|
||||
`jar tvf target/myproject-0.0.1-SNAPSHOT.jar`
|
||||
|
||||
|
||||
Alternatively u can go to https://start.spring.io/ and generate your starter project too
|
||||
here is one example with web dependency configured
|
||||
[spring web demo.zip](../../../../_resources/spring%20web%20demo.zip)
|
||||
|
||||
|
||||
|
||||
33
joplin notion extension/Web Development/Java/Spring/Intro.md
Normal file
33
joplin notion extension/Web Development/Java/Spring/Intro.md
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
Intro
|
||||
|
||||
https://www.youtube.com/watch?v=QuvS_VLbGko : crash course of 1hr
|
||||
|
||||
https://www.baeldung.com/
|
||||
|
||||
https://www.youtube.com/watch?v=Ch163VfHtvA&list=PLsyeobzWxl7oA8QOlMtQsRT_I7Rx2hoX4 : telusko playlist
|
||||
|
||||

|
||||
|
||||
### EJB (Enterprise java bean)
|
||||
- Three types of EJB
|
||||
1. Session bean : Contains business logic that is invoked by local, remote or web service client
|
||||
2. Message driven bean : Contains business logic that is invoked by passing message
|
||||
3. Entity bean : Encapsulates state that can be persisted in database. it is deprecated and replaced by java persistent API
|
||||
|
||||
|
||||
POJO : Plain Old Java Object . Ordinary object which is not bound by special restriction. https://www.javatpoint.com/pojo-in-java
|
||||
|
||||
|
||||
Interface : multiple inheritance feature in java
|
||||
annotations : Java Annotation is a tag that represents the metadata i.e. attached with class, interface, methods or fields to indicate some additional information which can be used by java compiler and JVM.
|
||||
eg: `@Override`, `@Deprecated`
|
||||
|
||||
|
||||
**Spring**
|
||||
An open source framework to build enterprise java applications on any deployment platform. It is a collection of subfraneworks called layers such as Spring AOP. Spring Object-Relational Mapping (Spring ORM). Spring Web Flow, and Spring Web MVC.
|
||||
Spring can integrate with other frameworks like hibernate and struts.
|
||||
|
||||
**Spring boot**
|
||||
We need to work on configuration thouroughly instead of coding itself. Spring boot solves this issue as spring boot comes with built in configurations and dependencies so developers can focus on conventions. We can add additional configurations too on top of basic ones.
|
||||
Spring boot provides us with embedded server/tomcat so instead of needing a separate server, JVM is enough. So JAR file will have embedded tomcat.
|
||||
There is no XML file so we can add properties in `application.properties`
|
||||
Loading…
Reference in a new issue