# Fix Jira Bug Tickets With Pull Requests in a Spring Boot App

Yes. An agent reads the Jira bug, finds the Spring Boot service at fault, reproduces it with a JUnit test, fixes it and links the pull request on the ticket.

[Run this on Rush](https://cloud.getrush.ai/run/fix-jira-bugs/spring-boot/), in a Project that has your repository.

## What the agent does

When a bug is filed, a Jira automation rule posts its key and summary to a handler on your server, and the handler sends the request on this page. The agent clones the repository into its own cloud sandbox and reads the ticket through your Atlassian connection, including the comments. In a system split into services the first question is which service owns the behaviour, and a ticket written from the UI ("the visit I added doesn't show on the pet") does not say; the agent answers it from the code.

In spring-petclinic/spring-petclinic-microservices the root `pom.xml` (parent `spring-boot-starter-parent` 4.0.1, `java.version` 17) builds eight modules: config, discovery and admin servers, the API gateway, a GenAI service, and the customers, vets and visits services. Owners and pets are in `spring-petclinic-customers-service`: `OwnerResource` under `/owners` and `PetResource` for `/owners/{ownerId}/pets` and `owners/*/pets/{petId}`. Visits are in `spring-petclinic-visits-service`, where `VisitResource` serves `owners/*/pets/{petId}/visits` and a batch read at `pets/visits?petId=`. The gateway's `CustomersServiceClient` and `VisitsServiceClient` combine the two for the UI, so a missing visit can be in the visits service, the gateway's merge, or the customers side.

The agent reads the endpoints the ticket touches closely, because the details are where bugs hide. `PetResource.processUpdateForm` takes `PUT /owners/*/pets/{petId}` but reads the pet id from the request body's `id`, not the path. Its private `save` sets the type only when `findPetTypeById(typeId)` finds one, so an unknown `typeId` leaves the old type in place with no error. Not-found cases throw `ResourceNotFoundException`, annotated `@ResponseStatus(NOT_FOUND)`, while `VisitResource.create` saves a visit for any `petId` of at least 1 without asking the customers service whether the pet exists. The agent matches the ticket to one of these paths, or to another it finds, before changing code.

Then it writes a JUnit test that fails the way the ticket describes, in the module that owns the code. `PetResourceTest` and `VisitResourceTest` are `@WebMvcTest` slices with `@ActiveProfiles("test")` and the repositories as `@MockitoBean`, and each service has `src/test/resources/application-test.yml`, so the tests need neither the config server nor Eureka. It fixes the code, runs `./mvnw test` for that module and then the whole build, opens a pull request with the ticket key in the title and branch, and comments on the ticket with the link.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "A Jira bug ticket was created; its key and summary follow this prompt. Use the Atlassian connection to read the ticket, its description and all comments. Work out which service owns the behaviour: spring-petclinic-customers-service (OwnerResource, PetResource), spring-petclinic-visits-service (VisitResource), or the API gateway's CustomersServiceClient and VisitsServiceClient. Reproduce the bug with a failing JUnit test in that module, in the existing @WebMvcTest style with @ActiveProfiles(\"test\") and @MockitoBean repositories. Fix the code, run ./mvnw test -pl <module> and then ./mvnw test for the whole build until both pass. Open a pull request with the ticket key in its title and branch name, then comment on the ticket with the pull request link, the service that was at fault and the cause in one sentence. If you cannot reproduce it, comment with what you tried and open no pull request.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is a pull request named after the ticket that changes one service, and says which one in its first line. In PetClinic microservices that is usually a resource class under `customers/web/` or `visits/web/`, or a client under the gateway's `api/application/`, plus a test method in the matching `*ResourceTest.java` or a new test beside it. The description explains why the bug lives in that service and not the others, shows the test that failed before the change and gives the `./mvnw test` result.

The ticket gets one comment with the pull request link and the service name, which helps whoever triages the next bug of the same kind. On GitHub the pull request runs the repository's `maven-build.yml`, which builds every module with `mvn -B package`, so a fix in one service that breaks a contract the gateway depends on shows up in the gateway's tests. The transcript keeps every command and its output.

Before merging, a reviewer checks that the change does not alter the JSON shape another service or the UI reads (the gateway's DTOs such as `PetDetails` and `VisitDetails` mirror these responses), that a new 404 or 400 is handled by the gateway rather than becoming a 500 there, and that the new test fails on `main`. When the agent could not reproduce the bug, there is no pull request and the ticket comment says what it tried.

## Run it on every new Jira bug

Create a Jira automation rule with trigger "Work item created", a condition on issue type Bug, and the action "Send web request" to your handler with `{{issue.key}}`, `{{issue.summary}}` and, if your project uses them, `{{issue.components.name}}`. The handler appends them to `input`, names your Atlassian connection in `connections` and sends one request per ticket; a component that already names the service saves the agent a step.

Give the API key a webhook URL and Rush POSTs `run.completed` or `run.failed` with the `session_url` when each turn finishes. A key runs at most `max_concurrent` sessions at once (4 by default) and answers `429` past that.

## Why run it on Rush?

Reproducing a bug in a multi-module Spring build means a JDK, the Maven wrapper resolving dependencies for eight modules, and knowing which module's tests to run. In a Rush sandbox the agent does that on its own machine; a developer's IDE, local Docker Compose stack and Maven cache stay as they were, and each ticket starts from a clean clone of `main`.

The proof is the test and where it lives: the transcript shows it failing in one module and the full build passing after the fix, the pull request's workflow builds every module again, and the Jira comment records which service owned the bug. Tickets that arrive together run in parallel, one sandbox each.

## Frequently asked questions

### Does it need the config server and Eureka running?

Not for the tests. Each service's `application.yml` imports the config server as `optional:`, and the `test` profile in `application-test.yml` is what the `@WebMvcTest` slices use. The agent only starts the whole system with Docker Compose if the bug cannot be shown in one service.

### What if the bug spans two services?

The agent says so in the pull request and keeps the change in the service where the cause is, with a test there. If both sides need a change, it puts them in one pull request with a test in each module, because the build compiles and tests them together.

### Can I send the Jira link in resources?

No. `resources` takes a GitHub repository or a Linear issue, and a Jira URL is `422 RESOURCE_UNSUPPORTED`. Send the key in the prompt and name your Atlassian connection in `connections`.

### Will it touch the GenAI service?

Only if the ticket is about it. `spring-petclinic-genai-service` is its own module, and the agent works in the module that owns the behaviour the ticket describes.
