Maximizing productivity is crucial for Java developers. This comprehensive guide covers essential tools, techniques, and best practices to streamline your Java development workflow and boost productivity.
Key areas covered:
// Essential Keyboard Shortcuts
Alt + Enter // Show intention actions and quick-fixes
Ctrl + Space // Basic code completion
Ctrl + Shift + Space // Smart code completion
Ctrl + N // Go to class
Ctrl + Shift + N // Go to file
Alt + F7 // Find usages
Shift + F6 // Rename
Ctrl + Alt + L // Reformat code
Ctrl + D // Duplicate line
Ctrl + / // Comment/uncomment line
Ctrl + Shift + / // Block comment
// Live Templates
// Create a custom live template for logging
log→
private static final Logger log = LoggerFactory.getLogger($CLASS$.class);
// JUnit test template
test→
@Test
void test$METHOD$() {
// Given
$END$
// When
// Then
}
// Essential Keyboard Shortcuts
Ctrl + Space // Content assist
Alt + / // Word completion
Ctrl + 1 // Quick fix
Ctrl + Shift + R // Open resource
Ctrl + O // Quick outline
Alt + Shift + R // Rename
Ctrl + Shift + F // Format code
Ctrl + D // Delete line
Ctrl + / // Toggle comment
Alt + ↑/↓ // Move lines
// Templates
// Create a logger
logger→
private static final Logger logger =
LoggerFactory.getLogger($className.class);
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>productivity-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<!-- Compiler Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
</plugin>
<!-- Surefire Plugin for Tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<!-- Spotless Plugin for Code Formatting -->
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>2.40.0</version>
<configuration>
<java>
<googleJavaFormat/>
<removeUnusedImports/>
</java>
</configuration>
</plugin>
</plugins>
</build>
</project>
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
id 'com.diffplug.spotless' version '6.23.3'
}
group = 'com.example'
version = '1.0-SNAPSHOT'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
spotless {
java {
googleJavaFormat()
removeUnusedImports()
trimTrailingWhitespace()
endWithNewline()
}
}
test {
useJUnitPlatform()
}
// Before Lombok
public class User {
private Long id;
private String username;
private String email;
public User() {}
public User(Long id, String username, String email) {
this.id = id;
this.username = username;
this.email = email;
}
// Getters and setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
// equals, hashCode, toString
}
// With Lombok
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
private Long id;
private String username;
private String email;
}
// DTO
@Data
public class UserDTO {
private Long id;
private String username;
private String email;
}
// Mapper Interface
@Mapper(componentModel = "spring")
public interface UserMapper {
UserDTO toDTO(User user);
User toEntity(UserDTO dto);
List<UserDTO> toDTOList(List<User> users);
List<User> toEntityList(List<UserDTO> dtos);
}
// Usage
@Service
@RequiredArgsConstructor
public class UserService {
private final UserMapper userMapper;
private final UserRepository userRepository;
public UserDTO createUser(UserDTO dto) {
User user = userMapper.toEntity(dto);
user = userRepository.save(user);
return userMapper.toDTO(user);
}
}
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@Mock
private UserMapper userMapper;
@InjectMocks
private UserService userService;
@Test
void createUser_Success() {
// Given
UserDTO dto = new UserDTO(null, "john", "john@example.com");
User user = new User(null, "john", "john@example.com");
User savedUser = new User(1L, "john", "john@example.com");
UserDTO expectedDto = new UserDTO(1L, "john", "john@example.com");
when(userMapper.toEntity(dto)).thenReturn(user);
when(userRepository.save(user)).thenReturn(savedUser);
when(userMapper.toDTO(savedUser)).thenReturn(expectedDto);
// When
UserDTO result = userService.createUser(dto);
// Then
assertThat(result).isEqualTo(expectedDto);
verify(userMapper).toEntity(dto);
verify(userRepository).save(user);
verify(userMapper).toDTO(savedUser);
}
}
@Testcontainers
@SpringBootTest
class UserRepositoryIntegrationTest {
@Container
static PostgreSQLContainer postgres =
new PostgreSQLContainer<>("postgres:15.4");
@DynamicPropertySource
static void registerPgProperties(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 createAndRetrieveUser() {
// Given
User user = new User(null, "john", "john@example.com");
// When
User savedUser = userRepository.save(user);
// Then
assertThat(savedUser.getId()).isNotNull();
assertThat(userRepository.findById(savedUser.getId()))
.isPresent()
.get()
.isEqualTo(savedUser);
}
}
// Add JVM arguments for remote debugging
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
// Docker configuration for remote debugging
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
- "5005:5005"
environment:
- JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
// IntelliJ IDEA Remote Debug Configuration
// Run > Edit Configurations > Add New Configuration > Remote JVM Debug
// Host: localhost
// Port: 5005
@Slf4j
@Service
public class UserService {
private final UserRepository userRepository;
public UserDTO createUser(UserDTO dto) {
log.debug("Creating user with username: {}", dto.getUsername());
try {
User user = userMapper.toEntity(dto);
user = userRepository.save(user);
log.info("Created user with ID: {}", user.getId());
return userMapper.toDTO(user);
} catch (Exception e) {
log.error("Failed to create user: {}", e.getMessage(), e);
throw new UserCreationException("Failed to create user", e);
}
}
public List<UserDTO> searchUsers(String query) {
log.debug("Searching users with query: {}", query);
StopWatch watch = new StopWatch();
watch.start();
List<User> users = userRepository.search(query);
watch.stop();
log.info("Found {} users in {} ms",
users.size(), watch.getTotalTimeMillis());
return userMapper.toDTOList(users);
}
}
// Maven configuration
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.10.0.2594</version>
</plugin>
// Gradle configuration
plugins {
id "org.sonarqube" version "4.4.1.3373"
}
sonar {
properties {
property "sonar.projectKey", "my-project"
property "sonar.projectName", "My Project"
property "sonar.host.url", "http://localhost:9000"
property "sonar.login", "your-token"
}
}
// GitHub Actions workflow
name: SonarQube Analysis
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Analyze
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: ./mvnw verify sonar:sonar
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<property name="severity" value="error"/>
<module name="TreeWalker">
<!-- Naming Conventions -->
<module name="MethodName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>
<!-- Code Layout -->
<module name="LeftCurly"/>
<module name="RightCurly"/>
<module name="NeedBraces"/>
<!-- Best Practices -->
<module name="FinalParameters"/>
<module name="MagicNumber"/>
<module name="AvoidStarImport"/>
</module>
<!-- File Level Checks -->
<module name="FileLength">
<property name="max" value="2000"/>
</module>
<module name="FileTabCharacter"/>
</module>
// Git commands for feature branch workflow
# Create and switch to feature branch
git checkout -b feature/user-management
# Keep branch up to date
git fetch origin
git rebase origin/main
# Stage and commit changes
git add .
git commit -m "feat: implement user management"
# Push changes
git push origin feature/user-management
# Create pull request
# After review and approval...
# Squash and merge
git checkout main
git pull
git branch -d feature/user-management
// Git commit message convention
feat: add user registration
^--^ ^-------------------^
| |
| +-> Summary in present tense
|
+-------> Type: feat, fix, docs, style, refactor, test, chore
// pre-commit hook
#!/bin/sh
echo "Running pre-commit checks..."
# Run tests
./mvnw test
if [ $? -ne 0 ]; then
echo "Tests must pass before commit!"
exit 1
fi
# Check code style
./mvnw spotless:check
if [ $? -ne 0 ]; then
echo "Code must be properly formatted!"
exit 1
fi
# Run static analysis
./mvnw sonar:sonar
if [ $? -ne 0 ]; then
echo "Static analysis must pass!"
exit 1
fi
exit 0
// pre-push hook
#!/bin/sh
echo "Running pre-push checks..."
# Run integration tests
./mvnw verify
if [ $? -ne 0 ]; then
echo "Integration tests must pass before push!"
exit 1
fi
exit 0
Improving Java development productivity requires a combination of proper tool usage, automation, and best practices. By implementing the techniques and tools discussed in this guide, you can significantly enhance your development workflow and code quality.
Remember to regularly evaluate and update your development practices, learn new tools, and stay updated with the latest productivity enhancements in the Java ecosystem.