Sunday, December 14, 2025

Java spring notes10

 Handson

1. Create spring boot appl to implement profiles

2.  You are developing an online store application where you need to manage products. You need to create entities for Product and use Spring Data JPA to perform the following operations:

 

1. Add new products to a category.

2. List all products under a specific category.

3. Update product details.

4. Delete a product by its ID.

 

 

1. Springboot Profiling

       In enterprise appl we have many env like dev, test, prod etc and each env needs different configuration related to that env and configured in application.properties, we cant configure everything in single file, so we have to use different properties file in different env and that concepts is called Profiling

 

a. we need to create different properties file related to env by application-profilename.properties (ie) application-dev.properties, application-prod.properties

 

b. By default springboot will read all configuration from application.properties, to configure which env properties file to read we have to provide

    spring.profiles.active=profilename

 

 

@Value - used to read single property from properties file to the controller prg, it use Spring Expression Language

 

@Profile - used to programmatically control files based on profiles

 

 

application.properties

server.port=2000

message=Welcome default user

spring.profiles.active=prod, dev

#always choose last one

 

application-dev.properties

server.port=2001

message=Welcome development user

 

application-prod.properties

server.port=2002

message=Welcome production user

 

@RestController

public class ProfileController {

 

              @Value("${server.port}") //SpEL

              private int port;

             

              @Value("${message}")

              private String msg;

             

              @GetMapping("/profile")

              public String getProfileInfo() {

                             return "Hello from controller: "+msg+" runs on port: "+port;

              }

}

 

@Configuration

@Profile("prod")

public class ProfileConfig {

   

              @PostConstruct

              public void print() {

                             System.out.println("This method should be printed only for prod profile");

              }

}

 

 

By default springboot will read all configuration from application.properties or application.yaml

 

 

application.properties

1. It is represented as sequence of key value pairs

 

server.port=2000

server.servlet.context-path=/app

spring.profiles.active=prod

 

2. This file is supported only in Java lang

 

3. support key value pair but both key and value should be in the form of string

 

4. If we want to handle multiple profiles then we have to create separate properties file

 

application.yml

1. It is represented as hierarchial format

 

server:

  port: 2000

  servlet:

     context-path: /app

 

spring:

  profiles:

     active: prod

 

2. This file is supported in Java, Python etc

 

3. Support scalar type(int, boolean, string, char), map, list, key value pair

 

4. We can handle multipl profiles in single yml file

 

 

server:

  port: 2000

  servlet:

     context-path: /app

 

spring:

  profiles:

     active: prod

 

---

spring:

  profiles: dev

server:

  port: 2001

---

spring:

  profiles: prod

server:

  port: 2002

 

 

2. By default springboot will read all configuration from application.properties or application.yaml present inside src/main/resources folder. But if we create the properties file in different name and in different location, then how springboot can read those properties file

 

@PropertySource - used to read single properties file present in different name and in different location

 

@PropertySources - used to read multiple properties file present in different name and in different location

 

@Value - used to read single property from properties file to the controller prg, it use Spring Expression Language

 

@ConfigurationProperties - used to map entire properties from properties file to separate java bean object

 

Lombok Developer Tool - Java annotation library which helps to reduce boilerplate code like getter, setter, default constructor, arg constructor, toString, equals and hashcode, logging

 

<dependency>

      <groupId>org.projectlombok</groupId>

      <artifactId>lombok</artifactId>

      <optional>true</optional>

    </dependency>

 

student.properties in src/main/resources

student.id=100

student.name=Ram

student.address=Chennai

student.age=25

 

student1.properties in c:/Training folder

student.email=ram@gmail.com

student.course=CSE

student.mark=89

 

@Configuration

//@PropertySource("classpath:student.properties")

//@PropertySource("file:\\C:\\Training\\student1.properties")

@PropertySources({

              @PropertySource("classpath:student.properties"),

              @PropertySource(file:\\C:\\Training\\student1.properties)

})

@ConfigurationProperties(prefix="student")

//@Getter

//@Setter

@Data  //@Getter+@Setter

@NoArgsConstructor

@AllArgsConstructor

//@ToString

//@EqualsAndHashCode

public class StudentConfig {

   private String name;

   private String address;

   private Integer age;

   private String email;

   private String course;

}

 

 

@RestController

public class StudentController {

             

              @Value("${student.id}")

              private Integer id;

             

              @Value("${student.mark}")

              private Integer mark;

 

              @Autowired

              StudentConfig config;

 

              @GetMapping("/stud")

              public String getStudentInfo() {

                             return id+" "+mark+" "+config.getName()+" "+config.getAddress();

              }

}

 

 

@Value

1. Accessing properties one by one

2. Support SpEL

3. Loose binding/Loose Grammar is not supported (ie) property name should be matching

4. Validation of properties is not supported

5. support only scalar datatype

 

@ConfigurationProperties

1. Bulk injection of properties

2. Dosent support SpEL

3. Loose binding/Loose Grammar is supported (ie) property name should be matching but we can also change the property only with special char and cases

4. Validation of properties is supported

5. support all datatype as well as objects

 

To validate the properties we have to provide spring-boot-starter-validation dependency

 

<dependency>

                                           <groupId>org.springframework.boot</groupId>

                                           <artifactId>spring-boot-starter-validation</artifactId>

                             </dependency>

 

@Validated - used to validate the properties

@Valid - used to validate the nested class properties

 

mail.properties in src/main/resources

#Scalar datatype

mail.to=abc@gmail.com

mail.from=xyz@gmail.com

mail.age=25

mail.first-name=Ram

mail.lastname=kumar

mail.middlename=T

 

#Complex datatype

mail.cc=efg@gmail.com,mno@gmail.com

mail.bcc=uvw@gmail.com,pqr@gmail.com

 

#Nested datatype

mail.credential.username=Ramu

mail.credential.password=abcd

 

 

@Configuration

@PropertySource("classpath:mail.properties")

@ConfigurationProperties(prefix="mail")

@Data

@AllArgsConstructor

@NoArgsConstructor

@Validated

public class MailConfig {

   @NotNull

   private String to;

   @NotNull

   private String from;

   @Max(value=40)

   @Min(value=20)

   private Integer age;

   @NotNull

   private String firstname;   //Loose binding

   private String LASTNAME; //Loose binding

   private String middle_name;  //Loose binding

  

   private String[] cc;

   private List<String> bcc;

  

   @Valid

   private Credential credential=new Credential();

  

   @Data

   public class Credential {

                 @NotNull

                 private String username;

                 @Size(min=4,max=8)

                 private String password;

   }

}

 

@RestController

public class MailController {

 

              @Autowired

              MailConfig config;

             

              @GetMapping("/mail")

              public String getMailInfo() {

                             return config.getFrom()+" "+config.getLASTNAME()+" "+config.getBcc()+" "+config.getCredential().getPassword();

              }

}

 

3. Springboot Interceptors

      - used to intercept client request and response

      - Interceptors are similar to Filters(only to Servlet), but interceptors are applied to the request that are sending to the controller

      - We have to implement an interface called HandlerInterceptor and override 3 methods

1. preHandle() - perform any operation before sending request to controller

2. postHandle() - perform any operation before sending response to client

3. afterCompletion() - perform any operation after completing request and response

 

 

1. Create controller prg

 

@RestController

@Slf4j

public class EmployeeController {

 

              @GetMapping("/emp")

              public String getEmpInfo() {

                             log.info("Inside employee controller");

                             return "Employee Information";

              }

}

 

2. Create Interceptor prg

 

@Component

@Slf4j

public class TimerInterceptor implements HandlerInterceptor {

 

              @Override

              public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

                                           throws Exception {

                             log.info("Inside preHandle");

                             request.setAttribute("startTime", System.currentTimeMillis());

                             return HandlerInterceptor.super.preHandle(request, response, handler);

              }

             

              @Override

              public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,

                                           ModelAndView modelAndView) throws Exception {

                             log.info("Inside postHandle");

                             HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);

              }

             

              @Override

              public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

                                           throws Exception {

                             log.info("Inside afterCompletion");

                             long totalTime=System.currentTimeMillis()-(long)request.getAttribute("startTime");

                             System.out.println("Total time taken is : "+totalTime);

              }

}

 

3. Configure interceptor for particular request

 

@Configuration

public class InterceptorConfig  implements WebMvcConfigurer{

             

              @Autowired

              TimerInterceptor timerInterceptor;

 

              @Override

              public void addInterceptors(InterceptorRegistry registry) {

                             //registry.addInterceptor(timerInterceptor); //this interceptor will be invoked for all request

                             registry.addInterceptor(timerInterceptor).addPathPatterns("/emp","/stud","/mail");

              }

}

 

 

Spring Data JPA

     - used to persist data into database

     - It is a library that adds as an extra layer of abstraction on top of JPA provider, mainly used to reduce work of developers at time of persisting the data

 

3 layers

1. Spring Data JPA - create JPA repository - 2 interface

a. JpaRepository<Entityclassname, datatype of PK> interface - used to perform CRUD as well as batch operation

   - T getById(int id) - Deprecated

   - T getOne(int id) - Deprecated

   - T getReferenceById(int id) - fetch single object based on id

   - List<> getAll() - fetch multiple object

   - T saveAndFlush(T t) - store single object into db table

   - void saveAllAndFlush(Iterable) - store multiple object into db table

   - void deleteAllByIdInBatch(Iterable)

   - void deleteAllInBatch()

b. JpaSpecificationExecutor<Entityclassname> interface - used to create dynamic queries

 

2. Spring Commons data layer - 3 interface

a. Repository<Entityclassname, datatype of PK> interface - marker interface

b. CrudRepository<Entityclassname, datatype of PK> interface - used to perform only CRUD operation

    - T save(T t) - store single object into db table

    - void saveAll(Iterable) - store multiple object into db table

    - Optional findById(int id) - fetch single object based on id

    - Iterable findAll() - return multiple objects

    - boolean existsById(int id)

    - boolean exists(T t)

    - void deleteById(int id)

    - void delete(T t)

    - void deleteAll()

c. PagingAndSortingRepository<Entityclassname, datatype of PK> interface - used for pagination and sorting purpose

 

3. JPA Provider - vendors that provide implementation for JPA specification like Hibernate, iBatis, JDO etc

 

 

Repository interface

  extends

CrudRepository interface

   extends

PagingAndSortingRepository interface

   extends

JpaRepository interface

 

 

1. Create Springboot project with spring data jpa, mysql driver, lombok dependency

 

2. Configure db info and hibernate properties in application.properties

 

spring.datasource.url=jdbc:mysql://localhost:3306/aspirejava

spring.datasource.username=root

spring.datasource.password=root

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.jpa.show-sql=true

spring.jpa.hibernate.ddl-auto= update

 

3. Create entity class

 

From SpringBoot 3.x onwards there is no javax, instead we use jakarta

 

@Entity

@Table(name="empl100")

@Data

@AllArgsConstructor

@NoArgsConstructor

public class Employee {

              @Id

    private Integer id;

    private String name;

    private String gender;

    private String email;

    private String dept;

    private Double salary;

}

 

4. Create repository interface

 

public interface EmployeeRepository extends JpaRepository<Employee, Integer>{

 

}

 

5.

 

@SpringBootApplication

public class SpringDataJpaApplication implements CommandLineRunner{

             

              @Autowired

              EmployeeRepository empRepo;

 

              public static void main(String[] args) {

                             SpringApplication.run(SpringDataJpaApplication.class, args);

              }

 

              @Override

              public void run(String... args) throws Exception {

                             //insertEmployee();

                             //fetchEmployee(100);

                             //fetchAllEmployee();

                             //updateEmployee(100);

                             deleteEmployee(100);

                            

              }

 

              private void deleteEmployee(int i) {

                             if(empRepo.existsById(i)) {

                                           //empRepo.deleteById(i);

                                           Employee e=empRepo.findById(i).get();

                                           empRepo.delete(e);

                             }

              }

 

              private void updateEmployee(int i) {

                             if(empRepo.existsById(i)) {

                                           Employee e=empRepo.findById(i).get();

                                           e.setSalary(25000.0);

                                           empRepo.save(e);

                             }

              }

 

              private void fetchAllEmployee() {

                             List<Employee> l=empRepo.findAll();

                             l.forEach(System.out::println);

              }

 

              private void fetchEmployee(int i) {

                             Optional op=empRepo.findById(i);

                             System.out.println(op.get());

              }

 

              private void insertEmployee() {

                             /*Employee e1=new Employee(100,"Ram","male",ram@gmail.com,"HR",20000.0);

                             empRepo.save(e1);*/

                            

                             List<Employee> l1=new ArrayList<>();

                             Employee e1=new Employee(101,"Sam","male",sam@gmail.com,"IT",30000.0);

                             l1.add(e1);

                             Employee e2=new Employee(102,"Saj","male",saj@gmail.com,"IT",35000.0);

                             l1.add(e2);

                             Employee e3=new Employee(103,"Amy","female",amy@gmail.com,"Sales",40000.0);

                             l1.add(e3);

                             Employee e4=new Employee(104,"Tim","male",tim@gmail.com,"HR",36000.0);

                             l1.add(e4);

                             Employee e5=new Employee(105,"John","male",john@gmail.com,"HR",45000.0);

                             l1.add(e5);

                             Employee e6=new Employee(106,"Lim","female",lim@gmail.com,"IT",42000.0);

                             l1.add(e6);

                             empRepo.saveAll(l1);

              }

 

}

No comments:

Post a Comment