java

📁 nguyenhuuca/assessment 📅 10 days ago
8
总安装量
7
周安装量
#35176
全站排名
安装命令
npx skills add https://github.com/nguyenhuuca/assessment --skill java

Agent 安装分布

mcpjam 7
claude-code 7
replit 7
junie 7
windsurf 7
zencoder 7

Skill 文档

Java Development

Project Setup

# Maven project
mvn archetype:generate -DgroupId=com.example -DartifactId=my-app \
  -DarchetypeArtifactId=maven-archetype-quickstart

# Spring Boot project
curl https://start.spring.io/starter.zip \
  -d dependencies=web,data-jpa,postgresql \
  -d type=maven-project \
  -d javaVersion=24 \
  -o project.zip

pom.xml (Java 24 with Preview Features)

<properties>
    <java.version>24</java.version>
    <maven.compiler.source>24</maven.compiler.source>
    <maven.compiler.target>24</maven.compiler.target>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <release>24</release>
                <compilerArgs>--enable-preview</compilerArgs>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <argLine>--enable-preview</argLine>
            </configuration>
        </plugin>
    </plugins>
</build>

Modern Java Features

Records (Java 14+)

// Immutable data class
public record User(Long id, String email, String name) {
    // Compact constructor for validation
    public User {
        if (email == null || !email.contains("@")) {
            throw new IllegalArgumentException("Invalid email");
        }
    }
}

// Usage
User user = new User(1L, "test@example.com", "John");
String email = user.email(); // Getter auto-generated

Pattern Matching (Java 21+)

// Pattern matching in switch
String format(Object obj) {
    return switch (obj) {
        case Integer i -> "int %d".formatted(i);
        case String s when s.length() > 10 -> "long string: %s".formatted(s);
        case String s -> "short string: %s".formatted(s);
        case null -> "null";
        default -> obj.toString();
    };
}

// Pattern matching in instanceof
if (obj instanceof String s && s.length() > 5) {
    System.out.println(s.toUpperCase());
}

Virtual Threads (Java 21+)

// Enable in Spring Boot
@Configuration
public class ThreadConfig {
    @Bean
    public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {
        return protocolHandler -> {
            protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
        };
    }
}

// Manual usage
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    List<Future<String>> futures = urls.stream()
        .map(url -> executor.submit(() -> fetchData(url)))
        .toList();

    for (Future<String> future : futures) {
        String result = future.get();
    }
}

StructuredTaskScope (Java 21+ Preview)

// Structured concurrency
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
    Future<String> user = scope.fork(() -> fetchUser(userId));
    Future<List<Order>> orders = scope.fork(() -> fetchOrders(userId));

    scope.join();           // Wait for all tasks
    scope.throwIfFailed();  // Propagate errors

    return new UserProfile(user.resultNow(), orders.resultNow());
}

Text Blocks (Java 15+)

String json = """
    {
        "name": "%s",
        "age": %d,
        "email": "%s"
    }
    """.formatted(name, age, email);

String sql = """
    SELECT u.id, u.name, o.total
    FROM users u
    JOIN orders o ON u.id = o.user_id
    WHERE u.status = 'ACTIVE'
    """;

Spring Boot Patterns

Controller with Validation

@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {

    private final UserService userService;

    @PostMapping
    public ResponseEntity<UserDto> create(@Valid @RequestBody CreateUserRequest request) {
        UserDto user = userService.create(request);
        return ResponseEntity.status(HttpStatus.CREATED).body(user);
    }

    @GetMapping("/{id}")
    public ResponseEntity<UserDto> getById(@PathVariable @Positive Long id) {
        return userService.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }
}

Service Layer

@Service
@Transactional
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    @Override
    public UserDto create(CreateUserRequest request) {
        // Validation
        if (userRepository.existsByEmail(request.email())) {
            throw new DuplicateEmailException("Email already exists");
        }

        // Business logic
        User user = User.builder()
            .email(request.email())
            .password(passwordEncoder.encode(request.password()))
            .createdAt(Instant.now())
            .build();

        User saved = userRepository.save(user);
        return mapToDto(saved);
    }

    @Override
    @Transactional(readOnly = true)
    public Optional<UserDto> findById(Long id) {
        return userRepository.findById(id)
            .map(this::mapToDto);
    }
}

Repository with Custom Query

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    boolean existsByEmail(String email);

    Optional<User> findByEmail(String email);

    @Query("""
        SELECT u FROM User u
        WHERE u.status = :status
        AND u.createdAt > :since
        ORDER BY u.createdAt DESC
        """)
    Page<User> findActiveUsers(
        @Param("status") UserStatus status,
        @Param("since") Instant since,
        Pageable pageable
    );

    @Modifying
    @Query("UPDATE User u SET u.lastLogin = :now WHERE u.id = :id")
    void updateLastLogin(@Param("id") Long id, @Param("now") Instant now);
}

Exception Handling

Custom Exception

public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

// Global exception handler
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
        ErrorResponse error = new ErrorResponse(
            HttpStatus.NOT_FOUND.value(),
            ex.getMessage(),
            Instant.now()
        );
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
        Map<String, String> errors = ex.getBindingResult()
            .getFieldErrors()
            .stream()
            .collect(Collectors.toMap(
                FieldError::getField,
                FieldError::getDefaultMessage
            ));

        ErrorResponse error = new ErrorResponse(
            HttpStatus.BAD_REQUEST.value(),
            "Validation failed",
            errors,
            Instant.now()
        );
        return ResponseEntity.badRequest().body(error);
    }
}

Testing

Unit Test with JUnit 5 & Mockito

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @Mock
    private PasswordEncoder passwordEncoder;

    @InjectMocks
    private UserServiceImpl userService;

    @Test
    void create_ValidRequest_ReturnsUser() {
        // Given
        CreateUserRequest request = new CreateUserRequest("test@example.com", "password");
        User savedUser = User.builder()
            .id(1L)
            .email(request.email())
            .build();

        when(userRepository.existsByEmail(request.email())).thenReturn(false);
        when(passwordEncoder.encode(request.password())).thenReturn("encoded");
        when(userRepository.save(any(User.class))).thenReturn(savedUser);

        // When
        UserDto result = userService.create(request);

        // Then
        assertThat(result.email()).isEqualTo("test@example.com");
        verify(userRepository).save(any(User.class));
    }

    @Test
    void create_DuplicateEmail_ThrowsException() {
        // Given
        CreateUserRequest request = new CreateUserRequest("test@example.com", "password");
        when(userRepository.existsByEmail(request.email())).thenReturn(true);

        // When & Then
        assertThrows(DuplicateEmailException.class, () -> userService.create(request));
        verify(userRepository, never()).save(any());
    }
}

Integration Test with TestContainers

@SpringBootTest
@Testcontainers
class UserRepositoryIntegrationTest {

    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
        .withDatabaseName("testdb");

    @DynamicPropertySource
    static void properties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
        registry.add("spring.datasource.username", postgres::getUsername);
        registry.add("spring.datasource.password", postgres::getPassword);
    }

    @Autowired
    private UserRepository userRepository;

    @Test
    void findByEmail_ExistingUser_ReturnsUser() {
        // Given
        User user = User.builder()
            .email("test@example.com")
            .password("password")
            .build();
        userRepository.save(user);

        // When
        Optional<User> found = userRepository.findByEmail("test@example.com");

        // Then
        assertThat(found).isPresent();
        assertThat(found.get().getEmail()).isEqualTo("test@example.com");
    }
}

REST API Test with MockMvc

@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Test
    void getById_ExistingUser_ReturnsOk() throws Exception {
        // Given
        UserDto user = new UserDto(1L, "test@example.com", "Test User");
        when(userService.findById(1L)).thenReturn(Optional.of(user));

        // When & Then
        mockMvc.perform(get("/api/users/1"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.email").value("test@example.com"))
            .andExpect(jsonPath("$.name").value("Test User"));
    }

    @Test
    void create_InvalidEmail_ReturnsBadRequest() throws Exception {
        // Given
        String requestBody = """
            {
                "email": "invalid-email",
                "password": "password"
            }
            """;

        // When & Then
        mockMvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content(requestBody))
            .andExpect(status().isBadRequest());
    }
}

Best Practices

Use Optional for Nullable Returns

// Good
public Optional<User> findById(Long id) {
    return userRepository.findById(id);
}

// Bad
public User findById(Long id) {
    return userRepository.findById(id).orElse(null);
}

Use Builder Pattern with Lombok

@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String email;
    private String password;

    @Builder.Default
    private Instant createdAt = Instant.now();
}

// Usage
User user = User.builder()
    .email("test@example.com")
    .password("encoded")
    .build();

Validation with Jakarta Bean Validation

public record CreateUserRequest(
    @NotBlank(message = "Email is required")
    @Email(message = "Invalid email format")
    String email,

    @NotBlank(message = "Password is required")
    @Size(min = 8, message = "Password must be at least 8 characters")
    String password
) {}

Tooling

# Maven commands
mvn clean install          # Build project
mvn test                   # Run tests
mvn verify                 # Run tests + integration tests
mvn jacoco:report          # Generate coverage report

# Run with preview features
mvn clean package
java --enable-preview -jar target/app.jar

# Spring Boot
mvn spring-boot:run        # Run application
mvn spring-boot:build-image # Build Docker image

Common Dependencies

<!-- Spring Boot -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <scope>provided</scope>
</dependency>

<!-- Testing -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

<!-- TestContainers -->
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>postgresql</artifactId>
    <scope>test</scope>
</dependency>