SDK Documentation

Java SDK

Enterprise-grade SDK for Java 8+ with Spring Boot and Kotlin support

Java 8+
Compatibility
Maven
& Gradle
Reactive
Support

Installation

Maven

<dependency>
    <groupId>dev.autonoma</groupId>
    <artifactId>autonoma-sdk</artifactId>
    <version>2.0.0</version>
</dependency>

Gradle

// Groovy DSL
implementation 'dev.autonoma:autonoma-sdk:2.0.0'

// Kotlin DSL
implementation("dev.autonoma:autonoma-sdk:2.0.0")

Spring Boot Starter

<dependency>
    <groupId>dev.autonoma</groupId>
    <artifactId>autonoma-spring-boot-starter</artifactId>
    <version>2.0.0</version>
</dependency>

Quick Start

Basic Usage

import dev.autonoma.sdk.Autonoma;
import dev.autonoma.sdk.AnalysisResult;
import dev.autonoma.sdk.Prediction;

public class Example {
    public static void main(String[] args) {
        // Initialize client
        Autonoma autonoma = Autonoma.builder()
            .apiKey(System.getenv("AUTONOMA_API_KEY"))
            .environment("production")
            .build();
        
        // Start monitoring
        autonoma.start();
        
        // Analyze code
        String content = Files.readString(Paths.get("App.java"));
        AnalysisResult result = autonoma.analyze(
            AnalyzeOptions.builder()
                .file("App.java")
                .content(content)
                .build()
        );
        
        // Get predictions
        List<Prediction> predictions = autonoma.getPredictions();
        
        // Apply auto-fix
        for (Prediction pred : predictions) {
            if (pred.isAutoFixAvailable()) {
                FixResult fixResult = autonoma.applyFix(pred.getId());
                System.out.println("Fix applied: " + fixResult.isSuccess());
            }
        }
        
        // Clean up
        autonoma.close();
    }
}

Spring Boot Integration

// application.yml
autonoma:
  api-key: ${AUTONOMA_API_KEY}
  environment: production
  auto-fix:
    enabled: true
    confidence-threshold: 0.95
  monitoring:
    enabled: true
    sample-rate: 1.0

// Main Application
@SpringBootApplication
@EnableAutonoma
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

// Service
@Service
public class UserService {
    
    @Autowired
    private Autonoma autonoma;
    
    @Monitored
    public User createUser(UserDto dto) {
        // Method is automatically monitored
        return userRepository.save(convertToEntity(dto));
    }
    
    @AutoFix
    public void processPayment(Payment payment) {
        // Autonoma will automatically fix issues in this method
        // when confidence is high enough
    }
}

// Controller with automatic error handling
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        // Errors are automatically captured by Autonoma
        return ResponseEntity.ok(userService.findById(id));
    }
}

Kotlin Support

import dev.autonoma.sdk.autonoma
import kotlinx.coroutines.*

fun main() = runBlocking {
    // DSL-style initialization
    val autonoma = autonoma {
        apiKey = System.getenv("AUTONOMA_API_KEY")
        environment = "production"
        autoFix {
            enabled = true
            confidenceThreshold = 0.95
        }
    }
    
    // Coroutine support
    val result = autonoma.analyzeAsync {
        file = "App.kt"
        content = File("App.kt").readText()
    }
    
    // Extension functions
    val predictions = autonoma.predictions()
        .filter { it.severity == Severity.CRITICAL }
        .map { it.applyFixIfAvailable() }
    
    // Flow support
    autonoma.predictionFlow()
        .filter { it.autoFixAvailable }
        .collect { prediction ->
            println("New prediction: ${prediction.message}")
        }
}

// Data class support
data class CustomMetric(
    val name: String,
    val value: Double,
    val tags: Map<String, String> = emptyMap()
)

// Extension function
suspend fun Prediction.applyFixIfAvailable(): FixResult? {
    return if (autoFixAvailable) {
        autonoma.applyFix(id)
    } else null
}

Reactive Programming

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Service
public class ReactiveService {
    
    private final ReactiveAutonoma autonoma;
    
    // Analyze files reactively
    public Flux<AnalysisResult> analyzeProject(String directory) {
        return Flux.fromIterable(Files.list(Paths.get(directory)))
            .filter(path -> path.toString().endsWith(".java"))
            .flatMap(path -> 
                Mono.fromCallable(() -> Files.readString(path))
                    .flatMap(content -> autonoma.analyze(
                        AnalyzeOptions.builder()
                            .file(path.toString())
                            .content(content)
                            .build()
                    ))
            );
    }
    
    // Stream predictions
    public Flux<Prediction> streamPredictions() {
        return autonoma.getPredictionsFlux()
            .filter(pred -> pred.getSeverity() == Severity.HIGH)
            .doOnNext(pred -> log.info("High severity: {}", pred.getMessage()));
    }
    
    // WebFlux integration
    @GetMapping(value = "/predictions/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<Prediction>> streamToClient() {
        return autonoma.getPredictionsFlux()
            .map(prediction -> ServerSentEvent.<Prediction>builder()
                .data(prediction)
                .build());
    }
}

Configuration Options

// Programmatic configuration
Autonoma autonoma = Autonoma.builder()
    // Required
    .apiKey("your-api-key")
    
    // Environment
    .environment(Environment.PRODUCTION)
    
    // API Configuration
    .baseUrl("https://api.autonoma.dev")
    .connectTimeout(Duration.ofSeconds(10))
    .readTimeout(Duration.ofSeconds(30))
    .maxRetries(3)
    .retryDelay(Duration.ofSeconds(1))
    
    // Features
    .autoFix(AutoFixConfig.builder()
        .enabled(true)
        .confidenceThreshold(0.95)
        .requireApproval(false)
        .excludePatterns(Arrays.asList("*Test.java", "*/generated/*"))
        .maxFixesPerRun(10)
        .build())
    
    // Monitoring
    .monitoring(MonitoringConfig.builder()
        .captureErrors(true)
        .capturePerformance(true)
        .captureCustomMetrics(true)
        .samplingRate(1.0)
        .captureStackTraces(true)
        .build())
    
    // Security
    .encryption(true)
    .anonymization(AnonymizationConfig.builder()
        .enabled(true)
        .patterns(Arrays.asList(
            Pattern.compile("password\\s*=\\s*["'].*?["']"),
            Pattern.compile("apiKey\\s*=\\s*["'].*?["']")
        ))
        .build())
    
    // Performance
    .batchSize(100)
    .flushInterval(Duration.ofSeconds(5))
    .threadPoolSize(4)
    
    // Logging
    .logger(LoggerFactory.getLogger("autonoma"))
    .logLevel(LogLevel.INFO)
    
    // Callbacks
    .onPrediction(pred -> log.info("New prediction: {}", pred))
    .onFix(fix -> log.info("Fix applied: {}", fix))
    .onError(error -> log.error("Autonoma error", error))
    
    .build();

// Spring Boot configuration (application.properties)
autonoma.api-key=${AUTONOMA_API_KEY}
autonoma.environment=production
autonoma.base-url=https://api.autonoma.dev
autonoma.auto-fix.enabled=true
autonoma.auto-fix.confidence-threshold=0.95
autonoma.monitoring.enabled=true
autonoma.monitoring.sample-rate=1.0
autonoma.security.encryption=true
autonoma.performance.batch-size=100
autonoma.performance.flush-interval=5s

Configuration Profiles

Support for multiple environments:

# application-dev.yml
autonoma:
  environment: development
  monitoring:
    sample-rate: 0.1

# application-prod.yml
autonoma:
  environment: production
  monitoring:
    sample-rate: 1.0

Builder Pattern

Fluent API for easy configuration:

Autonoma autonoma = Autonoma.builder()
    .withDefaults()
    .apiKey(getApiKey())
    .enableAutoFix()
    .build();

Core Methods

analyze(AnalyzeOptions options)

Analyze code for potential issues, performance problems, and security vulnerabilities.

// Single file analysis
AnalysisResult result = autonoma.analyze(
    AnalyzeOptions.builder()
        .file("UserService.java")
        .content(fileContent)
        .context(Map.of(
            "framework", "spring",
            "javaVersion", "11"
        ))
        .build()
);

// Batch analysis
List<AnalysisResult> results = autonoma.analyzeBatch(
    Arrays.asList(
        AnalyzeOptions.builder().file("Service.java").content(content1).build(),
        AnalyzeOptions.builder().file("Controller.java").content(content2).build()
    )
);

// With specific rules
AnalysisResult result = autonoma.analyze(
    AnalyzeOptions.builder()
        .file("PaymentService.java")
        .content(content)
        .rules(Arrays.asList("security", "performance"))
        .severityThreshold(Severity.MEDIUM)
        .build()
);

// Async analysis
CompletableFuture<AnalysisResult> future = autonoma.analyzeAsync(options);
future.thenAccept(result -> {
    System.out.printf("Found %d issues in %s%n", 
        result.getPredictions().size(), 
        result.getFile());
});

// Stream processing
Files.walk(Paths.get("src"))
    .filter(path -> path.toString().endsWith(".java"))
    .parallel()
    .map(path -> autonoma.analyze(createOptions(path)))
    .forEach(this::processResult);

getPredictions(PredictionFilters filters)

Retrieve predictions for your codebase with optional filtering.

// Get all predictions
List<Prediction> predictions = autonoma.getPredictions();

// Filter by severity and type
PredictionFilters filters = PredictionFilters.builder()
    .severities(Arrays.asList(Severity.CRITICAL, Severity.HIGH))
    .type("security")
    .status(PredictionStatus.OPEN)
    .build();
List<Prediction> filtered = autonoma.getPredictions(filters);

// With pagination
Page<Prediction> page = autonoma.getPredictionsPaged(
    filters,
    PageRequest.of(0, 50, Sort.by("severity").descending())
);

// Stream processing
autonoma.getPredictions().stream()
    .filter(pred -> pred.getConfidence() > 0.9)
    .filter(Prediction::isAutoFixAvailable)
    .forEach(pred -> autonoma.applyFix(pred.getId()));

// Group by severity
Map<Severity, List<Prediction>> bySeverity = 
    autonoma.getPredictions().stream()
        .collect(Collectors.groupingBy(Prediction::getSeverity));

applyFix(String predictionId, FixOptions options)

Apply an auto-fix for a specific prediction with validation and rollback support.

// Apply fix with default settings
FixResult result = autonoma.applyFix("pred_123abc");

// Apply with options
FixOptions options = FixOptions.builder()
    .dryRun(true)           // Preview changes
    .createBackup(true)     // Backup before applying
    .runTests(true)         // Run tests after fix
    .testCommand("mvn test")
    .autoCommit(false)
    .commitMessage("fix: resolve SQL injection vulnerability")
    .build();
FixResult result = autonoma.applyFix("pred_123abc", options);

// Handle result
if (result.isSuccess()) {
    System.out.println("Fix applied successfully!");
    System.out.printf("Files changed: %d%n", result.getFilesChanged().size());
    System.out.printf("Lines modified: %d%n", result.getLinesModified());
    
    // Review changes
    result.getChanges().forEach(change -> {
        System.out.printf("  %s: %s%n", change.getFile(), change.getDescription());
    });
} else {
    System.err.printf("Fix failed: %s%n", result.getError());
    
    // Rollback if available
    if (result.getRollbackId() != null) {
        autonoma.rollback(result.getRollbackId());
    }
}

// Batch fixes with transaction support
TransactionTemplate txTemplate = new TransactionTemplate(txManager);
txTemplate.execute(status -> {
    try {
        List<String> predictionIds = getHighConfidencePredictions();
        BatchFixResult batchResult = autonoma.applyFixes(
            predictionIds,
            BatchFixOptions.builder()
                .stopOnError(true)
                .parallel(false)
                .build()
        );
        
        if (!batchResult.isAllSuccessful()) {
            status.setRollbackOnly();
        }
        return batchResult;
    } catch (Exception e) {
        status.setRollbackOnly();
        throw e;
    }
});

Monitoring Methods

Monitor application performance and errors in real-time.

// Start monitoring
autonoma.start();

// Capture exceptions
try {
    riskyOperation();
} catch (Exception e) {
    autonoma.captureException(e, 
        ErrorContext.builder()
            .user(userId)
            .tags(Map.of(
                "component", "payment",
                "version", "2.1.0"
            ))
            .extra(Map.of(
                "orderId", orderId,
                "amount", amount
            ))
            .build()
    );
}

// Performance timing
try (Timer timer = autonoma.startTimer("database.query")) {
    return jdbcTemplate.query(sql, rowMapper);
} // Timer automatically records duration

// Custom metrics
autonoma.metric("api.requests", 1, 
    MetricTags.of("endpoint", "/api/users", "method", "GET"));

autonoma.gauge("queue.size", queue.size());
autonoma.histogram("response.size", response.length());

// Annotation-based monitoring
@Timed("user.service.create")
@Counted("user.created")
public User createUser(UserDto dto) {
    return userRepository.save(convertToEntity(dto));
}

// Method interceptor for automatic monitoring
@Bean
public MethodInterceptor autonomaInterceptor(Autonoma autonoma) {
    return invocation -> {
        String methodName = invocation.getMethod().getName();
        try (Timer timer = autonoma.startTimer("method." + methodName)) {
            return invocation.proceed();
        } catch (Exception e) {
            autonoma.captureException(e);
            throw e;
        }
    };
}

Advanced Features

Custom Rules

// Define custom rule
@Rule("no-system-out")
public class NoSystemOutRule implements AutonomaRule {
    @Override
    public List<Issue> analyze(CompilationUnit cu) {
        List<Issue> issues = new ArrayList<>();
        
        cu.findAll(MethodCallExpr.class).stream()
            .filter(call -> call.toString().startsWith("System.out"))
            .forEach(call -> issues.add(
                Issue.builder()
                    .severity(Severity.WARNING)
                    .message("Use logger instead of System.out")
                    .line(call.getBegin().get().line)
                    .fix(generateLoggerFix(call))
                    .build()
            ));
        
        return issues;
    }
}

// Register rules
autonoma.addRule(new NoSystemOutRule());
autonoma.addRuleSet(companyStandardsRuleSet);

// XML configuration
<autonoma-rules>
    <rule id="sql-injection" severity="critical">
        <pattern>Statement.*execute\(.*\+.*\)</pattern>
        <message>Potential SQL injection</message>
    </rule>
</autonoma-rules>

AspectJ Integration

@Aspect
@Component
public class AutonomaAspect {
    
    @Autowired
    private Autonoma autonoma;
    
    @Around("@annotation(monitored)")
    public Object monitor(ProceedingJoinPoint pjp, 
                         Monitored monitored) throws Throwable {
        String name = monitored.value().isEmpty() 
            ? pjp.getSignature().getName() 
            : monitored.value();
            
        try (Timer timer = autonoma.startTimer(name)) {
            return pjp.proceed();
        } catch (Exception e) {
            autonoma.captureException(e);
            throw e;
        }
    }
    
    @AfterReturning(
        pointcut = "@annotation(autoFix)",
        returning = "result"
    )
    public void autoFix(JoinPoint jp, 
                       AutoFix autoFix, 
                       Object result) {
        // Analyze method after execution
        autonoma.analyzeMethod(
            jp.getTarget().getClass(),
            jp.getSignature().getName()
        );
    }
}

Testing Integration

// JUnit 5 Extension
@ExtendWith(AutonomaExtension.class)
class UserServiceTest {
    
    @Test
    @AnalyzeTest
    void testCreateUser() {
        // Test runs normally
        User user = userService.createUser(dto);
        assertNotNull(user.getId());
        
        // Autonoma analyzes test and code under test
    }
    
    @ParameterizedTest
    @AutonomaSource("test-cases.json")
    void testWithAutonomaData(TestCase testCase) {
        // Autonoma provides test data based on
        // code analysis and coverage gaps
    }
}

// Custom test rule
@TestRule
public AutonomaTestRule autonomaRule = 
    AutonomaTestRule.builder()
        .failOnIssues(Severity.HIGH)
        .autoFix(true)
        .generateReport(true)
        .build();

// Mockito integration
@Mock
private Autonoma mockAutonoma;

@Test
void testWithMock() {
    when(mockAutonoma.analyze(any()))
        .thenReturn(AnalysisResult.empty());
        
    // Test your code
}

// Test containers
@Testcontainers
class IntegrationTest {
    @Container
    private static AutonomaContainer autonoma = 
        new AutonomaContainer("autonoma:latest")
            .withApiKey("test-key");
}

Build Tool Plugins

<!-- Maven Plugin -->
<plugin>
    <groupId>dev.autonoma</groupId>
    <artifactId>autonoma-maven-plugin</artifactId>
    <version>2.0.0</version>
    <configuration>
        <apiKey>${env.AUTONOMA_API_KEY}</apiKey>
        <failOnSeverity>HIGH</failOnSeverity>
        <autoFix>true</autoFix>
        <excludes>
            <exclude>**/generated/**</exclude>
        </excludes>
    </configuration>
    <executions>
        <execution>
            <phase>verify</phase>
            <goals>
                <goal>analyze</goal>
            </goals>
        </execution>
    </executions>
</plugin>

// Gradle Plugin
plugins {
    id 'dev.autonoma.gradle' version '2.0.0'
}

autonoma {
    apiKey = System.getenv('AUTONOMA_API_KEY')
    failOnSeverity = 'HIGH'
    autoFix = true
    excludes = ['**/generated/**']
}

// Custom task
task autonomaReport(type: AutonomaReportTask) {
    outputDir = file('build/reports/autonoma')
    format = 'html'
}

Microservices Support

Distributed Tracing

// Spring Cloud Sleuth integration
@Configuration
@EnableAutoConfiguration
public class AutonomaTracingConfig {
    
    @Bean
    public TracingCustomizer autonomaTracingCustomizer(Autonoma autonoma) {
        return builder -> builder
            .addSpanHandler(new AutonomaSpanHandler(autonoma))
            .addSpanExporter(new AutonomaSpanExporter(autonoma));
    }
}

// Service mesh support
@Component
public class AutonomaInterceptor implements ClientHttpRequestInterceptor {
    
    @Override
    public ClientHttpResponse intercept(HttpRequest request, 
                                      byte[] body, 
                                      ClientHttpRequestExecution execution) {
        // Add trace headers
        request.getHeaders().add("X-Autonoma-Trace-Id", 
            autonoma.getCurrentTraceId());
        
        try (Span span = autonoma.startSpan("http.client")) {
            span.tag("http.method", request.getMethod().toString());
            span.tag("http.url", request.getURI().toString());
            
            ClientHttpResponse response = execution.execute(request, body);
            span.tag("http.status", response.getStatusCode().value());
            
            return response;
        }
    }
}

// Kafka integration
@Component
public class AutonomaKafkaListener {
    
    @KafkaListener(topics = "orders")
    @AutonomaTrace
    public void processOrder(Order order, 
                           @Header("autonoma-trace-id") String traceId) {
        autonoma.continueTrace(traceId);
        // Process order with tracing
    }
}

// Circuit breaker integration
@Component
public class PaymentService {
    
    @CircuitBreaker(name = "payment", fallbackMethod = "fallbackPayment")
    @AutonomaMonitor
    public PaymentResult processPayment(Payment payment) {
        return externalPaymentService.process(payment);
    }
    
    public PaymentResult fallbackPayment(Payment payment, Exception e) {
        autonoma.captureException(e, ErrorContext.builder()
            .tags(Map.of("fallback", "true"))
            .build());
        return PaymentResult.failed("Service unavailable");
    }
}

Error Handling

import dev.autonoma.sdk.exceptions.*;

try {
    AnalysisResult result = autonoma.analyze(options);
} catch (RateLimitException e) {
    // Rate limit exceeded
    log.warn("Rate limit hit, retry after: {}", e.getRetryAfter());
    Thread.sleep(e.getRetryAfter().toMillis());
    // Retry operation
    
} catch (ApiException e) {
    // API errors (4xx, 5xx)
    if (e.getStatusCode() == 401) {
        log.error("Invalid API key");
    } else if (e.getStatusCode() == 403) {
        log.error("Access forbidden: {}", e.getMessage());
    } else {
        log.error("API error {}: {}", e.getStatusCode(), e.getMessage());
    }
    
} catch (ValidationException e) {
    // Input validation errors
    log.error("Validation failed for field '{}': {}", 
        e.getField(), e.getMessage());
    e.getErrors().forEach(error -> 
        log.error("  - {}: {}", error.getField(), error.getMessage())
    );
    
} catch (NetworkException e) {
    // Network connectivity issues
    log.error("Network error: {}", e.getMessage());
    // Implement retry logic or fallback
    
} catch (AutonomaException e) {
    // Generic Autonoma exception
    log.error("Autonoma error: {}", e.getMessage(), e);
}

// Global exception handler
@ControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(AutonomaException.class)
    public ResponseEntity<ErrorResponse> handleAutonomaException(
            AutonomaException e) {
        autonoma.captureException(e);
        return ResponseEntity.status(500)
            .body(new ErrorResponse("Internal error occurred"));
    }
}

// Retry template
RetryTemplate retryTemplate = RetryTemplate.builder()
    .maxAttempts(3)
    .exponentialBackoff(1000, 2, 10000)
    .retryOn(NetworkException.class)
    .retryOn(RateLimitException.class)
    .build();

AnalysisResult result = retryTemplate.execute(context -> 
    autonoma.analyze(options)
);

Best Practices

Resource Management

  • • Use try-with-resources for timers/spans
  • • Configure appropriate thread pool sizes
  • • Implement proper shutdown hooks
  • • Monitor memory usage with large batches

Performance

  • • Use async methods for non-blocking ops
  • • Enable batching for bulk operations
  • • Configure connection pooling properly
  • • Use reactive streams for large datasets

Security

  • • Never hardcode API keys
  • • Use secure credential storage
  • • Enable encryption for sensitive data
  • • Regularly rotate API keys

CI/CD Integration

  • • Add to build pipeline early
  • • Configure quality gates
  • • Enable automatic fixes for safe issues
  • • Generate reports for tracking

Ready to Get Started?

Add Autonoma to your Java project and start improving code quality