Java Operator SDK Implementation
/**
* POST TITLE: Java Operator SDK - Building Kubernetes Operators in Java
* 
* Complete implementation of Kubernetes operators using Java Operator SDK
*/
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
import io.javaoperatorsdk.operator.api.*;
import io.javaoperatorsdk.operator.api.reconciler.*;
import io.javaoperatorsdk.operator.processing.event.source.EventSource;
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
import io.fabric8.kubernetes.api.model.*;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.Resource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.time.Duration;
import java.util.*;
@ControllerConfiguration
public class JavaOperatorSDKDemo {
/**
* Custom Resource Definition: WebApp
*/
public static class WebApp extends CustomResource<WebAppSpec, WebAppStatus> 
implements Namespaced {
@Override
protected WebAppSpec initSpec() {
return new WebAppSpec();
}
@Override
protected WebAppStatus initStatus() {
return new WebAppStatus();
}
}
/**
* WebApp Spec Definition
*/
public static class WebAppSpec {
private String image;
private int replicas;
private int port;
private Map<String, String> env;
private Resources resources;
private String serviceType;
// Getters and setters
public String getImage() { return image; }
public void setImage(String image) { this.image = image; }
public int getReplicas() { return replicas; }
public void setReplicas(int replicas) { this.replicas = replicas; }
public int getPort() { return port; }
public void setPort(int port) { this.port = port; }
public Map<String, String> getEnv() { return env; }
public void setEnv(Map<String, String> env) { this.env = env; }
public Resources getResources() { return resources; }
public void setResources(Resources resources) { this.resources = resources; }
public String getServiceType() { return serviceType; }
public void setServiceType(String serviceType) { this.serviceType = serviceType; }
}
/**
* Resource requirements
*/
public static class Resources {
private String memory;
private String cpu;
public Resources() {}
public Resources(String memory, String cpu) {
this.memory = memory;
this.cpu = cpu;
}
// Getters and setters
public String getMemory() { return memory; }
public void setMemory(String memory) { this.memory = memory; }
public String getCpu() { return cpu; }
public void setCpu(String cpu) { this.cpu = cpu; }
}
/**
* WebApp Status Definition
*/
public static class WebAppStatus {
private String phase;
private String message;
private List<DeploymentStatus> deployments;
private List<ServiceStatus> services;
private int availableReplicas;
// Getters and setters
public String getPhase() { return phase; }
public void setPhase(String phase) { this.phase = phase; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public List<DeploymentStatus> getDeployments() { return deployments; }
public void setDeployments(List<DeploymentStatus> deployments) { this.deployments = deployments; }
public List<ServiceStatus> getServices() { return services; }
public void setServices(List<ServiceStatus> services) { this.services = services; }
public int getAvailableReplicas() { return availableReplicas; }
public void setAvailableReplicas(int availableReplicas) { this.availableReplicas = availableReplicas; }
}
public static class DeploymentStatus {
private String name;
private boolean ready;
private int replicas;
// Getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public boolean isReady() { return ready; }
public void setReady(boolean ready) { this.ready = ready; }
public int getReplicas() { return replicas; }
public void setReplicas(int replicas) { this.replicas = replicas; }
}
public static class ServiceStatus {
private String name;
private String clusterIP;
private String type;
// Getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getClusterIP() { return clusterIP; }
public void setClusterIP(String clusterIP) { this.clusterIP = clusterIP; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
}
/**
* WebApp Reconciler - The Core Operator Logic
*/
@ControllerConfiguration(
name = "webapp-controller",
generationAwareEventProcessing = false
)
public static class WebAppReconciler implements Reconciler<WebApp>, ContextInitializer<WebApp> {
private final KubernetesClient client;
private final Map<String, EventSource> eventSources;
public WebAppReconciler(KubernetesClient client) {
this.client = client;
this.eventSources = new ConcurrentHashMap<>();
}
@Override
public UpdateControl<WebApp> reconcile(WebApp webApp, Context<WebApp> context) {
String namespace = webApp.getMetadata().getNamespace();
String name = webApp.getMetadata().getName();
System.out.println("๐ŸŽฏ Reconciling WebApp: " + namespace + "/" + name);
try {
// 1. Create or Update Deployment
Deployment deployment = createDeployment(webApp);
client.apps().deployments().inNamespace(namespace).resource(deployment).createOrReplace();
// 2. Create or Update Service
Service service = createService(webApp);
client.services().inNamespace(namespace).resource(service).createOrReplace();
// 3. Update status
updateStatus(webApp, namespace);
System.out.println("โœ… Successfully reconciled WebApp: " + name);
return UpdateControl.updateStatus(webApp);
} catch (Exception e) {
System.err.println("โŒ Failed to reconcile WebApp: " + e.getMessage());
webApp.getStatus().setPhase("Failed");
webApp.getStatus().setMessage(e.getMessage());
return UpdateControl.updateStatus(webApp);
}
}
private Deployment createDeployment(WebApp webApp) {
WebAppSpec spec = webApp.getSpec();
String name = webApp.getMetadata().getName();
String namespace = webApp.getMetadata().getNamespace();
Map<String, String> labels = Map.of(
"app", name,
"managed-by", "webapp-operator"
);
// Container environment variables
List<EnvVar> envVars = new ArrayList<>();
if (spec.getEnv() != null) {
spec.getEnv().forEach((key, value) -> 
envVars.add(new EnvVarBuilder()
.withName(key)
.withValue(value)
.build())
);
}
// Resource requirements
io.fabric8.kubernetes.api.model.ResourceRequirements resources = null;
if (spec.getResources() != null) {
Resources res = spec.getResources();
resources = new io.fabric8.kubernetes.api.model.ResourceRequirementsBuilder()
.addToRequests("memory", new Quantity(res.getMemory()))
.addToRequests("cpu", new Quantity(res.getCpu()))
.addToLimits("memory", new Quantity(res.getMemory()))
.addToLimits("cpu", new Quantity(res.getCpu()))
.build();
}
return new DeploymentBuilder()
.withNewMetadata()
.withName(name)
.withNamespace(namespace)
.withLabels(labels)
.endMetadata()
.withNewSpec()
.withReplicas(spec.getReplicas())
.withNewSelector()
.withMatchLabels(labels)
.endSelector()
.withNewTemplate()
.withNewMetadata()
.withLabels(labels)
.endMetadata()
.withNewSpec()
.addNewContainer()
.withName(name)
.withImage(spec.getImage())
.withPorts(new ContainerPortBuilder()
.withContainerPort(spec.getPort())
.build())
.withEnv(envVars)
.withResources(resources)
.endContainer()
.endSpec()
.endTemplate()
.endSpec()
.build();
}
private Service createService(WebApp webApp) {
WebAppSpec spec = webApp.getSpec();
String name = webApp.getMetadata().getName();
String namespace = webApp.getMetadata().getNamespace();
Map<String, String> labels = Map.of(
"app", name,
"managed-by", "webapp-operator"
);
return new ServiceBuilder()
.withNewMetadata()
.withName(name)
.withNamespace(namespace)
.withLabels(labels)
.endMetadata()
.withNewSpec()
.withType(spec.getServiceType() != null ? spec.getServiceType() : "ClusterIP")
.withSelector(Map.of("app", name))
.addNewPort()
.withPort(spec.getPort())
.withTargetPort(new IntOrString(spec.getPort()))
.endPort()
.endSpec()
.build();
}
private void updateStatus(WebApp webApp, String namespace) {
String name = webApp.getMetadata().getName();
WebAppStatus status = webApp.getStatus();
try {
// Check deployment status
Deployment deployment = client.apps().deployments()
.inNamespace(namespace)
.withName(name)
.get();
if (deployment != null && deployment.getStatus() != null) {
status.setAvailableReplicas(
deployment.getStatus().getAvailableReplicas() != null ? 
deployment.getStatus().getAvailableReplicas() : 0
);
// Update deployment status
DeploymentStatus depStatus = new DeploymentStatus();
depStatus.setName(name);
depStatus.setReady(status.getAvailableReplicas() >= webApp.getSpec().getReplicas());
depStatus.setReplicas(webApp.getSpec().getReplicas());
status.setDeployments(List.of(depStatus));
}
// Check service status
Service service = client.services()
.inNamespace(namespace)
.withName(name)
.get();
if (service != null && service.getSpec() != null) {
ServiceStatus svcStatus = new ServiceStatus();
svcStatus.setName(name);
svcStatus.setClusterIP(service.getSpec().getClusterIP());
svcStatus.setType(service.getSpec().getType());
status.setServices(List.of(svcStatus));
}
status.setPhase("Ready");
status.setMessage("All components deployed successfully");
} catch (Exception e) {
status.setPhase("Unknown");
status.setMessage("Unable to determine status: " + e.getMessage());
}
}
@Override
public void initContext(Context<WebApp> context) {
System.out.println("๐Ÿ”ง Initializing context for WebApp reconciler");
}
@Override
public Map<String, EventSource> prepareEventSources(EventSourceContext<WebApp> context) {
return eventSources;
}
public void addEventSource(String name, EventSource eventSource) {
eventSources.put(name, eventSource);
}
}
/**
* Database Operator - More Complex Example
*/
public static class Database extends CustomResource<DatabaseSpec, DatabaseStatus> 
implements Namespaced {
@Override
protected DatabaseSpec initSpec() {
return new DatabaseSpec();
}
@Override
protected DatabaseStatus initStatus() {
return new DatabaseStatus();
}
}
public static class DatabaseSpec {
private String engine;
private String version;
private int replicas;
private Storage storage;
private Backup backup;
// Getters and setters
public String getEngine() { return engine; }
public void setEngine(String engine) { this.engine = engine; }
public String getVersion() { return version; }
public void setVersion(String version) { this.version = version; }
public int getReplicas() { return replicas; }
public void setReplicas(int replicas) { this.replicas = replicas; }
public Storage getStorage() { return storage; }
public void setStorage(Storage storage) { this.storage = storage; }
public Backup getBackup() { return backup; }
public void setBackup(Backup backup) { this.backup = backup; }
}
public static class Storage {
private String size;
private String storageClass;
public Storage() {}
public Storage(String size, String storageClass) {
this.size = size;
this.storageClass = storageClass;
}
// Getters and setters
public String getSize() { return size; }
public void setSize(String size) { this.size = size; }
public String getStorageClass() { return storageClass; }
public void setStorageClass(String storageClass) { this.storageClass = storageClass; }
}
public static class Backup {
private boolean enabled;
private String schedule;
private int retentionDays;
// Getters and setters
public boolean isEnabled() { return enabled; }
public void setEnabled(boolean enabled) { this.enabled = enabled; }
public String getSchedule() { return schedule; }
public void setSchedule(String schedule) { this.schedule = schedule; }
public int getRetentionDays() { return retentionDays; }
public void setRetentionDays(int retentionDays) { this.retentionDays = retentionDays; }
}
public static class DatabaseStatus {
private String phase;
private String message;
private String connectionString;
private boolean backupEnabled;
private List<DatabaseInstance> instances;
// Getters and setters
public String getPhase() { return phase; }
public void setPhase(String phase) { this.phase = phase; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public String getConnectionString() { return connectionString; }
public void setConnectionString(String connectionString) { this.connectionString = connectionString; }
public boolean isBackupEnabled() { return backupEnabled; }
public void setBackupEnabled(boolean backupEnabled) { this.backupEnabled = backupEnabled; }
public List<DatabaseInstance> getInstances() { return instances; }
public void setInstances(List<DatabaseInstance> instances) { this.instances = instances; }
}
public static class DatabaseInstance {
private String name;
private String role;
private boolean ready;
// Getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public boolean isReady() { return ready; }
public void setReady(boolean ready) { this.ready = ready; }
}
@ControllerConfiguration(
name = "database-controller",
generationAwareEventProcessing = false
)
public static class DatabaseReconciler implements Reconciler<Database> {
private final KubernetesClient client;
public DatabaseReconciler(KubernetesClient client) {
this.client = client;
}
@Override
public UpdateControl<Database> reconcile(Database database, Context<Database> context) {
String namespace = database.getMetadata().getNamespace();
String name = database.getMetadata().getName();
DatabaseSpec spec = database.getSpec();
System.out.println("๐ŸŽฏ Reconciling Database: " + namespace + "/" + name);
try {
// 1. Create StatefulSet for database
createStatefulSet(database);
// 2. Create Service
createDatabaseService(database);
// 3. Create Backup CronJob if enabled
if (spec.getBackup() != null && spec.getBackup().isEnabled()) {
createBackupCronJob(database);
}
// 4. Create ConfigMap for configuration
createConfigMap(database);
// 5. Update status
updateDatabaseStatus(database, namespace);
System.out.println("โœ… Successfully reconciled Database: " + name);
return UpdateControl.updateStatus(database);
} catch (Exception e) {
System.err.println("โŒ Failed to reconcile Database: " + e.getMessage());
database.getStatus().setPhase("Failed");
database.getStatus().setMessage(e.getMessage());
return UpdateControl.updateStatus(database);
}
}
private void createStatefulSet(Database database) {
// Implementation for database StatefulSet
System.out.println("Creating StatefulSet for database: " + database.getMetadata().getName());
}
private void createDatabaseService(Database database) {
// Implementation for database Service
System.out.println("Creating Service for database: " + database.getMetadata().getName());
}
private void createBackupCronJob(Database database) {
// Implementation for backup CronJob
System.out.println("Creating Backup CronJob for database: " + database.getMetadata().getName());
}
private void createConfigMap(Database database) {
// Implementation for database ConfigMap
System.out.println("Creating ConfigMap for database: " + database.getMetadata().getName());
}
private void updateDatabaseStatus(Database database, String namespace) {
DatabaseStatus status = database.getStatus();
status.setPhase("Ready");
status.setMessage("Database cluster is running");
status.setConnectionString("jdbc:" + database.getSpec().getEngine() + "://" + 
database.getMetadata().getName() + "." + namespace + ".svc.cluster.local");
status.setBackupEnabled(database.getSpec().getBackup() != null && 
database.getSpec().getBackup().isEnabled());
}
@Override
public DeleteControl cleanup(Database resource, Context<Database> context) {
System.out.println("๐Ÿงน Cleaning up Database: " + resource.getMetadata().getName());
// Implement cleanup logic
return DeleteControl.defaultDelete();
}
}
/**
* Operator Manager - Main Entry Point
*/
public static class OperatorManager {
private final KubernetesClient client;
private final Operator operator;
public OperatorManager() {
this.client = new KubernetesClientBuilder().build();
this.operator = new Operator(client);
}
public void start() {
System.out.println("๐Ÿš€ Starting Java Operator SDK...");
// Register reconcilers
operator.register(new WebAppReconciler(client));
operator.register(new DatabaseReconciler(client));
// Start the operator
operator.start();
System.out.println("โœ… Java Operator SDK started successfully");
}
public void stop() {
System.out.println("๐Ÿ›‘ Stopping Java Operator SDK...");
operator.stop();
System.out.println("โœ… Java Operator SDK stopped");
}
public void createWebApp(String namespace, String name, String image, int replicas) {
WebApp webApp = new WebApp();
webApp.setMetadata(new ObjectMetaBuilder()
.withName(name)
.withNamespace(namespace)
.build());
WebAppSpec spec = new WebAppSpec();
spec.setImage(image);
spec.setReplicas(replicas);
spec.setPort(8080);
spec.setEnv(Map.of(
"ENVIRONMENT", "production",
"LOG_LEVEL", "INFO"
));
spec.setResources(new Resources("512Mi", "500m"));
spec.setServiceType("ClusterIP");
webApp.setSpec(spec);
client.resources(WebApp.class)
.inNamespace(namespace)
.resource(webApp)
.create();
System.out.println("๐Ÿ“ฆ Created WebApp: " + namespace + "/" + name);
}
public void createDatabase(String namespace, String name, String engine, String version) {
Database database = new Database();
database.setMetadata(new ObjectMetaBuilder()
.withName(name)
.withNamespace(namespace)
.build());
DatabaseSpec spec = new DatabaseSpec();
spec.setEngine(engine);
spec.setVersion(version);
spec.setReplicas(1);
spec.setStorage(new Storage("10Gi", "standard"));
spec.setBackup(new Backup(true, "0 2 * * *", 7));
database.setSpec(spec);
client.resources(Database.class)
.inNamespace(namespace)
.resource(database)
.create();
System.out.println("๐Ÿ“ฆ Created Database: " + namespace + "/" + name);
}
}
/**
* Advanced Features: Event Sources and Filters
*/
public static class AdvancedWebAppReconciler extends WebAppReconciler {
public AdvancedWebAppReconciler(KubernetesClient client) {
super(client);
}
@Override
public UpdateControl<WebApp> reconcile(WebApp webApp, Context<WebApp> context) {
// Add custom logic before reconciliation
System.out.println("๐Ÿ” Advanced reconciliation for: " + webApp.getMetadata().getName());
// Check if resource has finalizer
if (!hasFinalizer(webApp)) {
addFinalizer(webApp);
return UpdateControl.updateResource(webApp);
}
// Handle deletion
if (isMarkedForDeletion(webApp)) {
return handleDeletion(webApp);
}
// Proceed with normal reconciliation
return super.reconcile(webApp, context);
}
private boolean hasFinalizer(WebApp webApp) {
List<String> finalizers = webApp.getMetadata().getFinalizers();
return finalizers != null && finalizers.contains("webapp-operator/finalizer");
}
private void addFinalizer(WebApp webApp) {
webApp.getMetadata().setFinalizers(List.of("webapp-operator/finalizer"));
System.out.println("๐Ÿ”’ Added finalizer to: " + webApp.getMetadata().getName());
}
private boolean isMarkedForDeletion(WebApp webApp) {
return webApp.getMetadata().getDeletionTimestamp() != null;
}
private UpdateControl<WebApp> handleDeletion(WebApp webApp) {
System.out.println("๐Ÿ—‘๏ธ Handling deletion for: " + webApp.getMetadata().getName());
// Perform cleanup operations
cleanupResources(webApp);
// Remove finalizer
removeFinalizer(webApp);
return UpdateControl.noUpdate();
}
private void cleanupResources(WebApp webApp) {
String namespace = webApp.getMetadata().getNamespace();
String name = webApp.getMetadata().getName();
// Delete associated resources
client.apps().deployments().inNamespace(namespace).withName(name).delete();
client.services().inNamespace(namespace).withName(name).delete();
System.out.println("๐Ÿงน Cleaned up resources for: " + name);
}
private void removeFinalizer(WebApp webApp) {
webApp.getMetadata().setFinalizers(null);
System.out.println("๐Ÿ”“ Removed finalizer from: " + webApp.getMetadata().getName());
}
}
/**
* Spring Boot Integration
*/
@Configuration
@EnableOperator
public static class OperatorConfiguration {
@Bean
public KubernetesClient kubernetesClient() {
return new KubernetesClientBuilder().build();
}
@Bean
public WebAppReconciler webAppReconciler(KubernetesClient client) {
return new WebAppReconciler(client);
}
@Bean
public DatabaseReconciler databaseReconciler(KubernetesClient client) {
return new DatabaseReconciler(client);
}
}
/**
* Demo and Usage Examples
*/
public static void main(String[] args) throws InterruptedException {
System.out.println("๐ŸŽฏ Java Operator SDK Demo");
System.out.println("=========================\n");
OperatorManager operatorManager = new OperatorManager();
// Start the operator
operatorManager.start();
// Wait a bit for operator to initialize
Thread.sleep(2000);
// Create sample resources
System.out.println("\n๐Ÿ“ Creating Sample Resources...");
// Create a WebApp
operatorManager.createWebApp("default", "my-webapp", "nginx:latest", 3);
// Create a Database
operatorManager.createDatabase("default", "my-database", "postgresql", "13");
// Keep running for demonstration
System.out.println("\nโณ Operator is running... Press Ctrl+C to stop");
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
operatorManager.stop();
}));
// Keep the main thread alive
Thread.sleep(300000); // 5 minutes
}
}

Maven Dependencies

<!-- pom.xml -->
<dependencies>
<!-- Java Operator SDK -->
<dependency>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework</artifactId>
<version>4.4.0</version>
</dependency>
<!-- Kubernetes Client -->
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client</artifactId>
<version>6.8.0</version>
</dependency>
<!-- Spring Boot Integration -->
<dependency>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-spring-boot-starter</artifactId>
<version>4.4.0</version>
</dependency>
</dependencies>

Custom Resource Definitions (YAML)

# webapp-crd.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: webapps.operator.demo.java
spec:
group: operator.demo.java
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
image:
type: string
replicas:
type: integer
port:
type: integer
env:
type: object
additionalProperties:
type: string
resources:
type: object
properties:
memory:
type: string
cpu:
type: string
serviceType:
type: string
status:
type: object
properties:
phase:
type: string
message:
type: string
availableReplicas:
type: integer
scope: Namespaced
names:
plural: webapps
singular: webapp
kind: WebApp
shortNames:
- wapp

This Java Operator SDK implementation provides:

  1. Complete operator framework for Kubernetes
  2. Custom Resource Definitions for WebApp and Database
  3. Reconciliation logic with proper status updates
  4. Resource management (Deployments, Services, StatefulSets)
  5. Advanced features like finalizers and cleanup
  6. Spring Boot integration for easy deployment
  7. Error handling and status reporting
  8. Event source management for efficient reconciliation

The operator follows Kubernetes best practices and can be extended for various use cases like database operators, ML pipeline operators, or any custom infrastructure automation needs.

Pyroscope Profiling in Java
Explains how to use Pyroscope for continuous profiling in Java applications, helping developers analyze CPU and memory usage patterns to improve performance and identify bottlenecks.
https://macronepal.com/blog/pyroscope-profiling-in-java/

OpenTelemetry Metrics in Java: Comprehensive Guide
Provides a complete guide to collecting and exporting metrics in Java using OpenTelemetry, including counters, histograms, gauges, and integration with monitoring tools. (MACRO NEPAL)
https://macronepal.com/blog/opentelemetry-metrics-in-java-comprehensive-guide/

OTLP Exporter in Java: Complete Guide for OpenTelemetry
Explains how to configure OTLP exporters in Java to send telemetry data such as traces, metrics, and logs to monitoring systems using HTTP or gRPC protocols. (MACRO NEPAL)
https://macronepal.com/blog/otlp-exporter-in-java-complete-guide-for-opentelemetry/

Thanos Integration in Java: Global View of Metrics
Explains how to integrate Thanos with Java monitoring systems to create a scalable global metrics view across multiple Prometheus instances.

https://macronepal.com/blog/thanos-integration-in-java-global-view-of-metrics

Time Series with InfluxDB in Java: Complete Guide (Version 2)
Explains how to manage time-series data using InfluxDB in Java applications, including storing, querying, and analyzing metrics data.

https://macronepal.com/blog/time-series-with-influxdb-in-java-complete-guide-2

Time Series with InfluxDB in Java: Complete Guide
Provides an overview of integrating InfluxDB with Java for time-series data handling, including monitoring applications and managing performance metrics.

https://macronepal.com/blog/time-series-with-influxdb-in-java-complete-guide

Implementing Prometheus Remote Write in Java (Version 2)
Explains how to configure Java applications to send metrics data to Prometheus-compatible systems using the remote write feature for scalable monitoring.

https://macronepal.com/blog/implementing-prometheus-remote-write-in-java-a-complete-guide-2

Implementing Prometheus Remote Write in Java: Complete Guide
Provides instructions for sending metrics from Java services to Prometheus servers, enabling centralized monitoring and real-time analytics.

https://macronepal.com/blog/implementing-prometheus-remote-write-in-java-a-complete-guide

Building a TileServer GL in Java: Vector and Raster Tile Server
Explains how to build a TileServer GL in Java for serving vector and raster map tiles, useful for geographic visualization and mapping applications.

https://macronepal.com/blog/building-a-tileserver-gl-in-java-vector-and-raster-tile-server

Indoor Mapping in Java
Explains how to create indoor mapping systems in Java, including navigation inside buildings, spatial data handling, and visualization techniques.

Leave a Reply

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


Macro Nepal Helper