- Here, School is Parent of Student, and Student is Parent of StudentProfile while defining relationships
-
See Student.java and StudentProfile.java to see
@OneToOneReltionship definition i.e Each Student has a StudentProfile -
See School.java and Student.java to see
@OneToManyand@ManyToOneRelationship definition as School has one to many relationship with Students i.e School has many Students
USING Jackson Annotations
-
School is PARENT of Student, so we add
@JsonManagedReferencein School.java where List of Stidents is defined which causes infinite recursion between Student and School, because student also has School defined.
This annotation means that Parent is responsible for serializing the child and child cannot serialize parent. -
Since Student is CHILD of School, we use
@JsonBackReferenceannotation in Student.java where School is instantiated. This means that Student entity/object doesnt need to serialize its parent i.e School
Now using this, we need to provide a lot of overhead and makes our Student object more and more complex. To overcome this, we use DTO which is the Data Transfer Object Pattern
- We want to hide sensitive information from outside world, hence we introduce a service or
mapperwhich helps hide that information like password, email, phone number, etc. Using a mapper, we can have multiple representations of an entity - So, to demonstrate DTO, we create a StudentDto Record, which contains name, email, and schoolId. We can add it into persistence DB by posting req on the url passing DTO object instead of student object
- See Postman Collection to undestand output of different APIs based on DTO or non-DTO. When running for First time, run
PostSchool/PostSchoolDto,PostStudent/PostSchoolDto, and then run other commands likeGet, Delete, etc
-
Check
StudenDto.javafor use of validation annotations. -
We apply validation to the bottommost layer where we ineract with data, hence validation is applied at DTO level, to validate data before posting.
-
These validations are valid with everything, even if you work with records, or simple classes
-
We need to add some annotations on field of objects to apply validation on them like
@NotEmpty -
To tell Spring which object is to be validated, use
@Validannotation in their defined part i.e, forStudentDtoobject, use@Validannotation inPOSTreq inStudentController.java -
We also define a
MethodArgumentNotValidExceptionHandler in Controller using@ExceptionHandlerto handle the Exception class by passing inMethodArgumentNotValidException.classto return a customResponseEntityinstead ofErrorMessage in Response when validation checks fail to undesrtand what the error is in response instead of checing console -
Creating Custom Exception Handler lets us give proper custom msg, for eg for StudentPost, with not specified firstName, and improper email format we get:
{
"firstName": "must not be empty",
"email": "must be a well-formed email address"
}
- To write custom message in output, we can directly define a
messageparameter in annotations, for eg:@NotEmpty(message="")
- Unit Testing
- Integration Testing
- End-to-End Testing
- A springboot application is SpringApplicationContext
- Springboot provides
@SpringBootTestannotation when you need Springboot features during test- for JUnit 4 ->
@RunWith(SpringRunner.class)to your test - For JUnit 5 -> No need to add the equivalent
@ExtendWith(SpringExtension)
- for JUnit 4 ->
- SpringBoot's auto-configuration system works well for applications but sometimes can be too much for tests
- It often helps to load only the parts of configuration that are required to test a "slice" of your application
- Each slice restricts component scan to appropriate classes and loads a very restricted set of auto-configuration class
- Keep same name as packages while testing (it can be created even without packages but it is ideal to create same package heirarchy)
- Go to file you want to create test file of and click
Source Action -> Generate Teststo create test files. - In IDE like IntelliJ and Eclipse, you can use other shortcuts to create as well
- In test, the methods should always be
publicand by adding@Testannotation over the method
Some Common Annotations:
@BeforeEachand@BeforeAllare the JUnit 5 equivalents of@Beforeand@BeforeClasspresent in JUnit 4. These annotations were renamed with clearer names to avoid confusion.- Methods annotated with the
@BeforeEachOR@Beforeannotation are run before each test. - Methods annotated with the
@AfterEachOR@Afterannotation are run after each test. - You can initialise data in BeforeEach and delete it in AfterEach as a good practise
@BeforeAlland@AfterAllare run before all methods of class are executed and and after all methods complete executing- If you're certain that the tests don't make any changes to those conditions, you can use
beforeAll(which will run once). If the tests do make changes to those conditions, then you would need to usebeforeEach, which will run before every test, so it can reset the conditions for the next one.
Perform Tests:
- To perform tests, we can use
assertMethods likeassertEquals, assertNotNull, and many moreto check for assertions in aGiven,When, andAssertformat like inStudentMapperTest.java
- Its when we want to run tests based on isolation from its dependencies, like keeping
Repositoryin isolation forServicetests. - So we
MOCKobjects to run the tests. It involves creating fake objects that stand in for real objects within the system. These fake objects, known as mock objects, can be used to test how different parts of the system interact with each other in a controlled environment. - We perform mocking in Springboot with
mockitoto perform mocking, which is like python'sunittest.mock - We create Mocks using the
@Mockannotation fromorg.mockitoto specify which objects to create mocks of. - To inject mocks as dependency for a object, we use
@InjectMocksannotation before constructor. InjectMocks will find any dependency having the@Mockannotation that matched the requirement. for eg, studentService will find methods with studentRepo and studentMapper - after initialising mocks, we need to tell mockito framework to start the mocks in current class using
MockitoAnnotations.openMocks(this)insetUpmethod in BeforeEach.thismeans that to open mocks in current class
- First POST School using DTO or normal
- Second, POST Student using DTO or normal
-
Install the
.jarfile frompackageson gitub -
After Installing use java command run the generated SNAPSHOT.jar file -
java -jar NAME_OF_FILE.jar
-
Install the dependencies needed to run the application and also downloading SNAPSHOT of production application -
mvn install -
After Installing using java command run the generated SNAPSHOT.jar file -
java -jar .\target\demo-0.0.1-SNAPSHOT.jar
- Directly run the
DemoApplication.javato locally run the code and to publish changes as well
- After extracting from Spring Initializr, comment JPA until repository is not implemented
- Use
@RestControllerand@RequestMappingfor defining path in Controller File. - Use
@Serviceto set Service file as Service Func. - Use
@Autowiredin both Controller and Service for Dependency Injection - For Table in DB, use
@Tableand@Entityand use necessary generators for different variables. - Use
@Repositoryin repository file - in Config file, use
@Configurationon class and@Beanfor method to add initial values in DB when running command - If we use
spring.jpa.hibernate.ddl-auto=create-drop, then there is need for Config, else use,...=update, to dont delete the DB Details when application reloads - To create a custom banner in springboot while booting, create banner.txt file in main/resources
- The central artifacts in Spring's Java configuration support are
@Configuration-annotated classes and@Bean-annotated methods. The@Beanannotation is used to indicate that a method instantiates, configures, and initializes a new object to be managed by the Spring IoC container. Spring's Inversion of Control (IoC)principle flips the script. With IoC, you delegate the responsibility of object creation and dependency management to the Spring container. Instead of creating objects explicitly, you define their dependencies through configuration files or annotations.
- Change the REPOSITORY on
/{user}/.m2/settings.xmland addOWNERandGITHUB_TOKEN - Add
Distrbution Managementinpom.xml


