google-site-verification: google61fe8ba583a51912.html
Accelerating Java Development: A Complete Guide to DevSpace for Local Development

Article

DevSpace is a powerful developer tool for Kubernetes that enables fast, efficient local development by creating a smooth development loop directly in your cluster. For Java developers, DevSpace eliminates the traditional "build, push, deploy" cycle, providing instant code synchronization, hot reloading, and streamlined debugging in a Kubernetes-native environment.

In this guide, we'll explore how to supercharge your Java development workflow with DevSpace, from basic setup to advanced development scenarios.

Why DevSpace for Java Development?

  • Instant Code Synchronization: See changes in seconds without rebuilding containers
  • Hot Reloading: Automatic application restarts on code changes
  • IDE-like Debugging: Direct debugging in Kubernetes pods
  • Consistent Environments: Develop in production-like Kubernetes environments
  • Team Standardization: Share development configurations across teams
  • Multi-Service Development: Work with multiple microservices simultaneously

Part 1: DevSpace Architecture Overview

1.1 How DevSpace Works with Java

Local Java Code → DevSpace Sync → Kubernetes Pod → Running Application ↓ ↓ ↓ ↓ IDE Changes File Sync Hot Reload Instant Feedback Debugging Port Forward Log Streaming Breakpoints

1.2 Project Structure

java-devspace-app/ ├── src/ │ ├── main/java/com/example/ │ └── test/java/com/example/ ├── .devspace/ │ ├── devspace.yaml │ └── commands.yaml ├── charts/ │ └── app/ │ ├── Chart.yaml │ ├── values.yaml │ └── templates/ ├── Dockerfile ├── Dockerfile.dev ├── devspace-start.sh └── pom.xml

Part 2: Setup and Configuration

2.1 Installation

macOS:

# Homebrew brew install devspace # Or curl curl -L -o devspace "https://github.com/loft-sh/devspace/releases/latest/download/devspace-darwin-amd64" && sudo install -c -m 0755 devspace /usr/local/bin

Linux:

curl -L -o devspace "https://github.com/loft-sh/devspace/releases/latest/download/devspace-linux-amd64" && sudo install -c -m 0755 devspace /usr/local/bin

Windows:

# Chocolatey choco install devspace # Or PowerShell iwr -useb 'https://github.com/loft-sh/devspace/releases/latest/download/devspace-windows-amd64.exe' -o devspace.exe

2.2 Basic DevSpace Configuration

# .devspace/devspace.yaml version: v2beta1 name: java-devspace-app # Variables vars: IMAGE_NAME: java-app REGISTRY: docker.io REPOSITORY: myorg JAVA_VERSION: 17 MAVEN_VERSION: 3.8.6 # Docker image building images: app: image: ${REGISTRY}/${REPOSITORY}/${IMAGE_NAME} tags: - latest - ${DEVSPACE_COMMIT} build: docker: dockerfile: ./Dockerfile.dev context: . options: buildArgs: JAVA_VERSION: ${JAVA_VERSION} MAVEN_VERSION: ${MAVEN_VERSION} # Development configuration dev: app: imageSelector: ${images.app.image} devImage: ${images.app.image} containers: - container: app restartHelper: enabled: true path: /restart # Deployment configuration deployments: - name: ${name} helm: componentChart: true values: containers: - image: ${images.app.image} name: app service: ports: - port: 8080 containerPort: 8080 # Development synchronization and port forwarding profiles: - name: dev patches: - op: add path: dev.app.containers.0.sync value: localSubPath: ./src containerPath: /app/src excludePaths: - "**/target/**" - "**/.git/**" - "**/node_modules/**" - "**/*.class" - op: add path: dev.app.containers.0.portForwarding value: - port: 5005 remotePort: 5005 - port: 8080 remotePort: 8080 - op: add path: dev.app.containers.0.logs value: enabled: true lastLines: 100 - name: debug patches: - op: add path: dev.app.containers.0.debug value: enabled: true remoteEnabled: true # Dependencies (for microservices) dependencies: - name: database source: git: https://github.com/myorg/devspace-database subPath: charts/database # Hooks for automation hooks: - command: ./scripts/pre-dev.sh events: before: deploy - command: ./scripts/post-dev.sh events: after: deploy

Part 3: Docker Configuration for Development

3.1 Development Dockerfile

# Dockerfile.dev FROM maven:${MAVEN_VERSION:-3.8.6}-openjdk-${JAVA_VERSION:-17} as dev # Install additional development tools RUN apt-get update && apt-get install -y \ curl \ git \ vim \ net-tools \ iputils-ping \ dnsutils \ && rm -rf /var/lib/apt/lists/* # Create non-root user RUN groupadd -r spring && useradd -r -g spring spring # Set working directory WORKDIR /app # Copy Maven files for dependency caching COPY pom.xml . COPY .mvn/ .mvn/ COPY mvnw . # Download dependencies RUN mvn dependency:go-offline -B # Copy source code COPY src ./src # Create restart trigger file RUN mkdir -p /restart && touch /restart/.devrestart # Development environment variables ENV JAVA_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 -Dspring.devtools.restart.enabled=true -Dspring.devtools.restart.trigger-file=/restart/.devrestart" ENV MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=256m" # Expose ports EXPOSE 8080 5005 # Use non-root user USER spring # Development entry point CMD ["mvn", "spring-boot:run", "-Dspring-boot.run.jvmArguments=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005"]

3.2 Production Dockerfile

# Dockerfile # Build stage FROM maven:3.8.6-openjdk-17 AS builder WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline -B COPY src ./src RUN mvn clean package -DskipTests # Runtime stage FROM eclipse-temurin:17-jre-jammy RUN groupadd -r spring && useradd -r -g spring spring WORKDIR /app USER spring COPY --from=builder /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "/app/app.jar"]

Part 4: Java Application Configuration

4.1 Spring Boot Development Configuration

// File: src/main/java/com/example/DevSpaceApplication.java package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; @SpringBootApplication @EnableConfigurationProperties(DevSpaceProperties.class) public class DevSpaceApplication { public static void main(String[] args) { SpringApplication.run(DevSpaceApplication.class, args); } } // File: src/main/java/com/example/DevSpaceProperties.java package com.example; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "app.devspace") public record DevSpaceProperties( boolean hotReload, boolean remoteDebug, int debugPort, SyncConfig sync, LoggingConfig logging ) { public record SyncConfig( boolean enabled, String[] excludePatterns, int pollInterval ) {} public record LoggingConfig( boolean devTools, String level, boolean showSql ) {} }

4.2 Development-Specific Configuration

# src/main/resources/application-devspace.yaml app: devspace: hot-reload: true remote-debug: true debug-port: 5005 sync: enabled: true exclude-patterns: "**/target/**,**/test-output/**,**/.git/**" poll-interval: 1000 logging: dev-tools: true level: DEBUG show-sql: true spring: devtools: restart: enabled: true trigger-file: .devrestart poll-interval: 1000 quiet-period: 400 livereload: enabled: true jackson: serialization: indent-output: true logging: level: com.example: DEBUG org.springframework.web: DEBUG org.hibernate.SQL: DEBUG org.hibernate.type.descriptor.sql.BasicBinder: TRACE management: endpoints: web: exposure: include: health,info,metrics,restart endpoint: restart: enabled: true health: show-details: always server: port: 8080

4.3 Development Controller with Hot Reload Support

// File: src/main/java/com/example/controller/DevSpaceController.java package com.example.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint; import org.springframework.core.env.Environment; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.time.LocalDateTime; import java.util.Map; @RestController @RequestMapping("/api/dev") public class DevSpaceController { private static final Logger logger = LoggerFactory.getLogger(DevSpaceController.class); private final Environment environment; public DevSpaceController(Environment environment) { this.environment = environment; } @GetMapping("/info") public ResponseEntity<Map<String, Object>> getDevInfo() { logger.debug("Development info endpoint called"); return ResponseEntity.ok(Map.of( "service", "java-devspace-app", "timestamp", LocalDateTime.now(), "profiles", environment.getActiveProfiles(), "hotReload", environment.getProperty("app.devspace.hot-reload", Boolean.class, false), "remoteDebug", environment.getProperty("app.devspace.remote-debug", Boolean.class, false), "devTools", environment.getProperty("spring.devtools.restart.enabled", Boolean.class, false) )); } @PostMapping("/restart") public ResponseEntity<Map<String, String>> triggerRestart() { logger.info("Manual restart triggered via DevSpace endpoint"); // This will trigger Spring Boot DevTools restart // In a real scenario, you might touch the trigger file return ResponseEntity.ok(Map.of( "status", "restart_triggered", "message", "Application restart has been triggered" )); } @GetMapping("/config") public ResponseEntity<Map<String, Object>> getConfig() { return ResponseEntity.ok(Map.of( "java.version", System.getProperty("java.version"), "user.dir", System.getProperty("user.dir"), "os.name", System.getProperty("os.name"), "spring.profiles.active", String.join(",", environment.getActiveProfiles()) )); } }

Part 5: Advanced DevSpace Configuration

5.1 Multi-Service Development

# .devspace/devspace-multi.yaml version: v2beta1 name: java-microservices-dev vars: REGISTRY: docker.io REPOSITORY: myorg images: user-service: image: ${REGISTRY}/${REPOSITORY}/user-service tags: ["latest"] build: docker: dockerfile: ./user-service/Dockerfile.dev context: ./user-service order-service: image: ${REGISTRY}/${REPOSITORY}/order-service tags: ["latest"] build: docker: dockerfile: ./order-service/Dockerfile.dev context: ./order-service api-gateway: image: ${REGISTRY}/${REPOSITORY}/api-gateway tags: ["latest"] build: docker: dockerfile: ./api-gateway/Dockerfile.dev context: ./api-gateway dev: user-service: imageSelector: ${images.user-service.image} containers: - container: app sync: - localSubPath: ./user-service/src containerPath: /app/src excludePaths: - "**/target/**" portForwarding: - port: 8081 remotePort: 8081 - port: 5006 remotePort: 5006 order-service: imageSelector: ${images.order-service.image} containers: - container: app sync: - localSubPath: ./order-service/src containerPath: /app/src portForwarding: - port: 8082 remotePort: 8082 - port: 5007 remotePort: 5007 api-gateway: imageSelector: ${images.api-gateway.image} containers: - container: app sync: - localSubPath: ./api-gateway/src containerPath: /app/src portForwarding: - port: 8080 remotePort: 8080 - port: 5005 remotePort: 5005 deployments: - name: user-service helm: componentChart: true values: containers: - image: ${images.user-service.image} service: ports: - port: 8081 - name: order-service helm: componentChart: true values: containers: - image: ${images.order-service.image} service: ports: - port: 8082 - name: api-gateway helm: componentChart: true values: containers: - image: ${images.api-gateway.image} service: ports: - port: 8080 profiles: - name: with-dependencies patches: - op: add path: dependencies value: - name: postgres source: git: https://github.com/loft-sh/component-charts subPath: postgresql version: 0.1.0 - name: redis source: git: https://github.com/loft-sh/component-charts subPath: redis version: 0.1.0

5.2 Custom Commands and Scripts

# .devspace/commands.yaml version: v1beta1 commands: - name: dev description: Start development mode with hot reload command: |- devspace dev --profile dev - name: debug description: Start development with remote debugging command: |- devspace dev --profile debug - name: build description: Build application image command: |- devspace build - name: deploy description: Deploy to development namespace command: |- devspace deploy --profile dev - name: logs description: Show application logs command: |- devspace logs -f - name: test description: Run tests in development environment command: |- devspace enter --container app -- mvn test - name: integration-test description: Run integration tests command: |- devspace run-pipeline integration-tests - name: clean description: Clean development environment command: |- devspace purge kubectl delete pod -l app.kubernetes.io/name=java-devspace-app - name: restart description: Restart development container command: |- devspace restart - name: status description: Show development status command: |- echo "=== Development Environment Status ===" kubectl get pods -l app.kubernetes.io/name=java-devspace-app echo "" echo "=== Port Forwarding ===" kubectl get svc -l app.kubernetes.io/name=java-devspace-app

5.3 Pipeline Configuration

# .devspace/pipelines.yaml version: v1beta1 pipelines: dev: run: |- devspace build --skip-push devspace deploy devspace dev integration-tests: run: |- devspace build --skip-push devspace deploy devspace enter --container app -- mvn verify debug: run: |- devspace build --skip-push devspace deploy devspace dev --debug reset: run: |- devspace purge kubectl delete pvc -l app.kubernetes.io/name=java-devspace-app

Part 6: Development Workflows

6.1 Startup Script

#!/bin/bash # devspace-start.sh set -e echo "🚀 Starting Java DevSpace Development Environment" # Check if DevSpace is installed if ! command -v devspace &> /dev/null; then echo "❌ DevSpace is not installed. Please install it first." echo " Visit: https://devspace.sh/cli/docs/getting-started/installation" exit 1 fi # Check if we have a Kubernetes context if ! kubectl config current-context &> /dev/null; then echo "❌ No Kubernetes context found. Please configure kubectl." exit 1 fi echo "✅ Kubernetes context: $(kubectl config current-context)" # Build and start development environment echo "📦 Building application image..." devspace build echo "🚀 Deploying to Kubernetes..." devspace deploy echo "🔧 Starting development mode with hot reload..." devspace dev --profile dev echo "🎉 Development environment is ready!" echo " Application: http://localhost:8080" echo " Actuator: http://localhost:8080/actuator" echo " Dev Info: http://localhost:8080/api/dev/info"

6.2 Development Makefile

# Makefile .DEFAULT_GOAL := help .PHONY: help dev debug build deploy test clean logs restart status help: @echo "Java DevSpace Development Commands:" @echo " make dev - Start development mode with hot reload" @echo " make debug - Start development with remote debugging" @echo " make build - Build application image" @echo " make deploy - Deploy to development namespace" @echo " make test - Run tests in development environment" @echo " make logs - Show application logs" @echo " make restart - Restart development container" @echo " make status - Show development status" @echo " make clean - Clean development environment" dev: ./devspace-start.sh debug: devspace dev --profile debug build: devspace build deploy: devspace deploy --profile dev test: devspace enter --container app -- mvn test integration-test: devspace run-pipeline integration-tests logs: devspace logs -f --tail 100 restart: devspace restart status: @echo "=== Development Environment Status ===" @kubectl get pods -l app.kubernetes.io/name=java-devspace-app @echo "" @echo "=== Services ===" @kubectl get svc -l app.kubernetes.io/name=java-devspace-app clean: devspace purge kubectl delete pod -l app.kubernetes.io/name=java-devspace-app purge-all: devspace purge kubectl delete all -l app.kubernetes.io/name=java-devspace-app kubectl delete pvc -l app.kubernetes.io/name=java-devspace-app

Part 7: IDE Integration

7.1 VS Code Configuration

// .vscode/launch.json { "version": "0.2.0", "configurations": [ { "type": "java", "name": "DevSpace Remote Debug", "request": "attach", "hostName": "localhost", "port": 5005, "projectName": "java-devspace-app" }, { "type": "java", "name": "DevSpace Test Debug", "request": "attach", "hostName": "localhost", "port": 5006, "projectName": "java-devspace-app" } ] }
// .vscode/settings.json { "java.configuration.updateBuildConfiguration": "automatic", "java.compile.nullAnalysis.mode": "automatic", "java.debug.settings.onBuildFailureProceed": true, "files.watcherExclude": { "**/target/**": true, "**/build/**": true }, "java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx2G -Xms100m -Xlog:disable" }

7.2 IntelliJ IDEA Configuration

<!-- .idea/runConfigurations/DevSpace_Remote_Debug.xml --> <component name="ProjectRunConfigurationManager"> <configuration default="false" name="DevSpace Remote Debug" type="Remote"> <module name="java-devspace-app" /> <option name="USE_SOCKET_TRANSPORT" value="true" /> <option name="SERVER_MODE" value="false" /> <option name="SHMEM_ADDRESS" /> <option name="HOST" value="localhost" /> <option name="PORT" value="5005" /> <option name="AUTO_RESTART" value="false" /> <RunnerSettings RunnerId="Debug" /> <ConfigurationWrapper RunnerId="Debug" /> <method v="2" /> </configuration> </component>

Part 8: Team Development Setup

8.1 Development Environment Bootstrap

# .devspace/team-setup.yaml version: v2beta1 name: java-team-dev vars: NAMESPACE: java-dev-${DEVSPACE_USERNAME} REGISTRY: docker.io REPOSITORY: myorg profiles: - name: team-dev patches: - op: replace path: deployments.helm.values.labels value: app.kubernetes.io/name: ${name} app.kubernetes.io/instance: ${DEVSPACE_USERNAME} - op: replace path: deployments.helm.values.namespace value: ${NAMESPACE} - op: add path: deployments.helm.values.ingress value: enabled: true hosts: - host: ${DEVSPACE_USERNAME}.dev.mycompany.com paths: - path: / pathType: Prefix commands: - name: team-init description: Initialize team development environment command: |- # Create namespace for user kubectl create namespace ${NAMESPACE} || true # Set up development context kubectl config set-context --current --namespace=${NAMESPACE} # Start development devspace dev --profile team-dev - name: team-cleanup description: Clean up team development environment command: |- kubectl delete namespace ${NAMESPACE} || true

8.2 Development Dependencies

# .devspace/dependencies.yaml version: v2beta1 dependencies: - name: postgresql source: git: https://github.com/bitnami/charts subPath: bitnami/postgresql version: 12.0.0 values: |- auth: postgresPassword: "devspace123" database: "java_app" primary: persistence: enabled: false - name: redis source: git: https://github.com/bitnami/charts subPath: bitnami/redis version: 17.0.0 values: |- architecture: standalone auth: enabled: false master: persistence: enabled: false - name: elasticsearch source: git: https://github.com/elastic/helm-charts subPath: elasticsearch version: 7.17.0 values: |- replicas: 1 minimumMasterNodes: 1 resources: requests: cpu: 100m memory: 512Mi limits: cpu: 1000m memory: 1Gi

Part 9: Troubleshooting and Optimization

9.1 Common Issues and Solutions

#!/bin/bash # scripts/troubleshoot-devspace.sh echo "🔧 DevSpace Troubleshooting Script" echo "1. Checking Kubernetes connection..." kubectl cluster-info echo "2. Checking current namespace..." kubectl config view --minify --output 'jsonpath={..namespace}'; echo echo "3. Checking DevSpace pods..." kubectl get pods -l app.kubernetes.io/name=java-devspace-app echo "4. Checking sync status..." devspace list sync echo "5. Checking port forwarding..." devspace list ports echo "6. Checking logs..." devspace logs --tail 50 echo "7. Restarting sync..." devspace sync --restart echo "✅ Troubleshooting complete"

9.2 Performance Optimization

# .devspace/optimized.yaml version: v2beta1 name: java-devspace-optimized profiles: - name: optimized patches: - op: replace path: images.app.build.docker.options value: buildArgs: JAVA_VERSION: "17" MAVEN_VERSION: "3.8.6" target: dev cacheFrom: - ${images.app.image}:latest - op: replace path: dev.app.containers.0.sync value: localSubPath: ./src containerPath: /app/src excludePaths: - "**/target/**" - "**/test-output/**" - "**/.git/**" - "**/node_modules/**" - "**/*.class" - "**/*.jar" - "**/logs/**" uploadExcludeFile: .dockerignore poll: false bandwidthLimits: false - op: add path: dev.app.containers.0.resources value: limits: memory: 1Gi cpu: 500m requests: memory: 512Mi cpu: 100m

Best Practices for DevSpace with Java

  1. Use Development-Specific Dockerfiles: Optimize for fast builds and hot reloading
  2. Leverage Sync Exclusions: Exclude build artifacts and dependencies from sync
  3. Configure Resource Limits: Prevent development containers from consuming too many resources
  4. Use Profiles: Create different profiles for debug, test, and team development
  5. Implement Health Checks: Ensure your application is ready before starting sync
  6. Version Control Configurations: Share DevSpace configurations across the team
  7. Monitor Performance: Use DevSpace analytics to optimize your development loop
  8. Secure Development: Use namespaced development environments for security

Conclusion

DevSpace revolutionizes Java development on Kubernetes by providing a seamless, fast, and efficient development experience. By implementing the patterns and configurations in this guide, you can:

  • Eliminate long build cycles with instant code synchronization
  • Debug applications directly in Kubernetes with full IDE integration
  • Maintain consistent environments across your development team
  • Streamline microservices development with multi-service support
  • Automate development workflows with custom commands and pipelines

The combination of DevSpace's powerful synchronization, Java's robust ecosystem, and Kubernetes' scalability creates an unparalleled development experience that accelerates feature development while maintaining production-like environment fidelity.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper