BAEL-4135 - When are static variables initialized? (#9607)
* Hexagonal Architecture in Java A quick and practical example of Hexagonal Architecture in Java * Fixed code formatting issues * When are static variables initialized Sample class and test class. * Revert "When are static variables initialized" This reverts commit c781923093ccc88bc269bea276653169065cb17b. * Revert "Revert "When are static variables initialized"" This reverts commit 2bffdf401d4e7dc2cefd7eb16357b2d51271edad. * New java module for static variable Created a new core-java-lang-3 module for static variables. * PR review changes: Added more scenarios to the static variable test Covered the following cases: 1. Variable initialization in a static block 2. Variable initialization in a static nested class
This commit is contained in:
parent
60ef1c8551
commit
dc06936a5d
|
@ -39,4 +39,4 @@
|
|||
<assertj.version>3.12.2</assertj.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
</project>
|
|
@ -0,0 +1,23 @@
|
|||
package com.baeldung.staticvariables;
|
||||
|
||||
public class StaticVariableDemo {
|
||||
public static int i;
|
||||
public static int j = 20;
|
||||
public static int z;
|
||||
|
||||
static {
|
||||
z = 30;
|
||||
a = 40;
|
||||
}
|
||||
|
||||
public static int a = 50;
|
||||
|
||||
public static final int b = 100;
|
||||
|
||||
public StaticVariableDemo() {
|
||||
}
|
||||
|
||||
static class Nested {
|
||||
public static String nestedClassStaticVariable = "test";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
package com.baeldung.staticvariables;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class StaticVariableUnitTest {
|
||||
|
||||
@Test
|
||||
public void initializeStaticVariable_checkAssignedValues() {
|
||||
|
||||
try {
|
||||
Class<?> staticVariableDemo = this.getClass()
|
||||
.getClassLoader()
|
||||
.loadClass("com.baeldung.staticvariables.StaticVariableDemo");
|
||||
|
||||
Field field1 = staticVariableDemo.getField("i");
|
||||
|
||||
assertThat(field1.getInt(staticVariableDemo)).isEqualTo(0);
|
||||
|
||||
Field field2 = staticVariableDemo.getField("j");
|
||||
|
||||
assertThat(field2.getInt(staticVariableDemo)).isEqualTo(20);
|
||||
|
||||
} catch (ClassNotFoundException | NoSuchFieldException | SecurityException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initializeStaticVariable_checkStaticBlock() {
|
||||
|
||||
try {
|
||||
Class<?> staticVariableDemo = this.getClass()
|
||||
.getClassLoader()
|
||||
.loadClass("com.baeldung.staticvariables.StaticVariableDemo");
|
||||
|
||||
Field field1 = staticVariableDemo.getField("z");
|
||||
|
||||
assertThat(field1.getInt(staticVariableDemo)).isEqualTo(30);
|
||||
|
||||
Field field2 = staticVariableDemo.getField("a");
|
||||
|
||||
assertThat(field2.getInt(staticVariableDemo)).isEqualTo(50);
|
||||
|
||||
} catch (ClassNotFoundException | NoSuchFieldException | SecurityException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initializeStaticVariable_checkFinalValues() {
|
||||
|
||||
try {
|
||||
Class<?> staticVariableDemo = this.getClass()
|
||||
.getClassLoader()
|
||||
.loadClass("com.baeldung.staticvariables.StaticVariableDemo");
|
||||
|
||||
Field field1 = staticVariableDemo.getField("b");
|
||||
|
||||
assertThat(field1.getInt(staticVariableDemo)).isEqualTo(100);
|
||||
|
||||
} catch (ClassNotFoundException | NoSuchFieldException | SecurityException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initializeStaticVariable_checkInnerClassValues() {
|
||||
|
||||
try {
|
||||
Class<?> staticVariableDemo = this.getClass()
|
||||
.getClassLoader()
|
||||
.loadClass("com.baeldung.staticvariables.StaticVariableDemo");
|
||||
|
||||
Class<?>[] nestedClasses = staticVariableDemo.getClasses();
|
||||
|
||||
for (Class<?> nestedClass : nestedClasses) {
|
||||
if (nestedClass.getName()
|
||||
.equals("Nested")) {
|
||||
|
||||
Field field1 = nestedClass.getField("nestedClassStaticVariable");
|
||||
assertThat(field1.get(nestedClass)).isEqualTo("test");
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ClassNotFoundException | NoSuchFieldException | SecurityException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.3.0.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>hexagonal-architecture</artifactId>
|
||||
<version>1.0</version>
|
||||
<name>hexagonal-architecture</name>
|
||||
<description>Project for hexagonal architecture in java</description>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.pattern.hexagonal;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class HexArchApplicationDemo {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(HexArchApplicationDemo.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.pattern.hexagonal.config;
|
||||
|
||||
import com.baeldung.pattern.hexagonal.domain.services.EmployeeService;
|
||||
import com.baeldung.pattern.hexagonal.domain.services.EmployeeServiceImpl;
|
||||
import com.baeldung.pattern.hexagonal.persistence.EmployeeRepository;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
@Bean
|
||||
public EmployeeService getEmployeeService(EmployeeRepository employeeRepository) {
|
||||
return new EmployeeServiceImpl(employeeRepository);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.pattern.hexagonal.config;
|
||||
|
||||
import com.baeldung.pattern.hexagonal.persistence.MongoRepoEx;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
||||
|
||||
@Configuration
|
||||
@EnableMongoRepositories(basePackageClasses = MongoRepoEx.class)
|
||||
public class MongoConfig {
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.baeldung.pattern.hexagonal.controller;
|
||||
|
||||
import com.baeldung.pattern.hexagonal.domain.model.Employee;
|
||||
import com.baeldung.pattern.hexagonal.domain.services.EmployeeService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/employees")
|
||||
public class EmployeeController {
|
||||
@Autowired
|
||||
EmployeeService employeeService;
|
||||
|
||||
@PostMapping(produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
@ResponseBody
|
||||
public Employee addEmployee(@RequestBody Employee employee) {
|
||||
return employeeService.addEmployee(employee);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/{employeeId}")
|
||||
public Employee getEmployee(@PathVariable("employeeId") String employeeId) {
|
||||
return employeeService.getEmployee(employeeId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.baeldung.pattern.hexagonal.domain.model;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Employee {
|
||||
@Id
|
||||
private String empId;
|
||||
private String empName;
|
||||
private String empJobTitle;
|
||||
|
||||
public String getEmpId() {
|
||||
return empId;
|
||||
}
|
||||
|
||||
public void setEmpId(String empId) {
|
||||
this.empId = empId;
|
||||
}
|
||||
|
||||
public String getEmpName() {
|
||||
return empName;
|
||||
}
|
||||
|
||||
public void setEmpName(String empName) {
|
||||
this.empName = empName;
|
||||
}
|
||||
|
||||
public String getEmpJobTitle() {
|
||||
return empJobTitle;
|
||||
}
|
||||
|
||||
public void setEmpJobTitle(String empJobTitle) {
|
||||
this.empJobTitle = empJobTitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
Employee employee = (Employee) o;
|
||||
return empId.equals(employee.empId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(empId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.pattern.hexagonal.domain.services;
|
||||
|
||||
import com.baeldung.pattern.hexagonal.domain.model.Employee;
|
||||
|
||||
public interface EmployeeService {
|
||||
|
||||
Employee addEmployee(Employee employee);
|
||||
|
||||
Employee getEmployee(String employeeId);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.baeldung.pattern.hexagonal.domain.services;
|
||||
|
||||
import com.baeldung.pattern.hexagonal.domain.model.Employee;
|
||||
import com.baeldung.pattern.hexagonal.persistence.EmployeeRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class EmployeeServiceImpl implements EmployeeService {
|
||||
|
||||
private EmployeeRepository employeeRepository;
|
||||
|
||||
@Autowired
|
||||
public EmployeeServiceImpl(EmployeeRepository employeeRepository) {
|
||||
this.employeeRepository = employeeRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Employee addEmployee(Employee employee) {
|
||||
return employeeRepository.add(employee);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Employee getEmployee(String employeeId) {
|
||||
Optional<Employee> employee = employeeRepository.findById(employeeId);
|
||||
|
||||
if (employee.isPresent()) {
|
||||
return employee.get();
|
||||
} else {
|
||||
// throw
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.pattern.hexagonal.persistence;
|
||||
|
||||
import com.baeldung.pattern.hexagonal.domain.model.Employee;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface EmployeeRepository {
|
||||
|
||||
Employee add(Employee employee);
|
||||
|
||||
Optional<Employee> findById(String id);
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.baeldung.pattern.hexagonal.persistence;
|
||||
|
||||
import com.baeldung.pattern.hexagonal.domain.model.Employee;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public class MongoDBRepository implements EmployeeRepository {
|
||||
|
||||
@Autowired
|
||||
MongoRepoEx mongoRepository;
|
||||
|
||||
@Override
|
||||
public Employee add(Employee employee) {
|
||||
return mongoRepository.insert(employee);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Employee> findById(String id) {
|
||||
return mongoRepository.findById(id);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.baeldung.pattern.hexagonal.persistence;
|
||||
|
||||
import com.baeldung.pattern.hexagonal.domain.model.Employee;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface MongoRepoEx extends MongoRepository<Employee, String> {
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
package com.baeldung.pattern.hexagonal.domain.services;
|
||||
|
||||
import com.baeldung.pattern.hexagonal.domain.model.Employee;
|
||||
import com.baeldung.pattern.hexagonal.persistence.EmployeeRepository;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class EmployeeServiceImplTest {
|
||||
|
||||
private EmployeeRepository employeeRepository;
|
||||
private EmployeeService testService;
|
||||
private Employee testModel;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
employeeRepository = mock(EmployeeRepository.class);
|
||||
|
||||
testService = new EmployeeServiceImpl(employeeRepository);
|
||||
testModel = new Employee();
|
||||
testModel.setEmpId("2000");
|
||||
testModel.setEmpName("Test user 1");
|
||||
testModel.setEmpJobTitle("Software engineer");
|
||||
}
|
||||
|
||||
@Test
|
||||
void addEmployee() {
|
||||
when(employeeRepository.add(any(Employee.class))).thenReturn(testModel);
|
||||
|
||||
Employee testResponse = testService.addEmployee(testModel);
|
||||
assertEquals(testModel, testResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getEmployee() {
|
||||
when(employeeRepository.findById("2000")).thenReturn(Optional.of(testModel));
|
||||
|
||||
Employee testResponse = testService.getEmployee("2000");
|
||||
assertEquals(testModel, testResponse);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue