{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreiarfbgedsazhqcanihp6rfrwa6wtyje3eba7tomyx2orttczthcda",
    "uri": "at://did:plc:vyjlfm46mfv6u4vjp6qtrfx2/app.bsky.feed.post/3mmcjne2e5rj2"
  },
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreidg2k33tiuupnstmiowh7hyyvtsbe3gyhfygiytrzynysnhoctrxi"
    },
    "mimeType": "image/jpeg",
    "size": 81260
  },
  "path": "/articles/find-a-bar-for-this-one",
  "publishedAt": "2026-05-20T06:30:00.000Z",
  "site": "https://thedailywtf.com",
  "tags": [
    "CodeSOD",
    "Learn more.",
    "@Inject",
    "@Transaction"
  ],
  "textContent": "A depressing quantity of software is what I would call a \"data pump\". I have some data over here, and I need it over there. Maybe I'm integrating into a legacy app. Or into an ERP. Or into a 3rd party API. At the end of the day, I have data in one place, and I want it in another place.\n\n**Sally** has a Java application written in the Quarkus framework, which has a nightly batch that works to keep a table of `Bar` entities in sync with a table of `Foo` entities. (This anonymization comes from Sally) These exist in the same database. There is also a `Bar` webservice, which provides information about the `Bar` entities. The workflow, such as it is, is that the software needs to find all of the `Foo` entities that do not currently have associated `Bar` entities, and then call the `Bar` webservice to get the required information to create those `Bar` entities.\n\nLet's see how that works.\n\n\n    @Inject UserTransaction transaction\n    // If this is annotated with @Transaction the usage in the Message function down below will have some Thread exception\n    public List<FooData> getAllFoos() {\n      try{\n        return fooDataRepository.findAllFoos();\n      } catch (Exception e) {\n        throw new RuntimeException(e);\n      }\n    }\n\n\nWe'll worry about that comment in a second, but this function returns a list of all of the `Foo` objects in the database. It does _not_ return a list of _all the`Foo` objects without associated `Bar` entities_. It's just the whole giant list of everything. The underlying database is a standard relational database; it'd be trivially easy to write that query, even going through the ORM.\n\nWell, that's bad, but it's all pretty minor. How does the actual update go?\n\n\n    // Can't be annotated with @Transaction because Oracle DB can handle the given Amount of dataEntities in one Transaction '\\._./'\n    Message updateBarsWithFoos() {\n      List<FooData> foos = getAllFoos();\n      if(!foos.isEmpty()){\n        foos.forEach(foo -> {\n          try{\n            transaction.begin();\n            if(barRepository.findByName(foo.getName()) == null){\n              if(barDataService.searchByName(foo.getName()) != null && barDataService.searchByName(foo.getName()).marker() != null){\n                barRepository.createBar(barDataService.searchByName(foo.getName()));\n              }\n            }\n            transaction.commit();\n          } catch (Exception e) {\n            try {\n              transaction.rollback();\n            } catch (Exception ex) {\n              throw new RuntimeException(ex);\n            }\n          }\n        });\n      }\n      return new Message(MessageLevel.INFO, \"Created bars\")\n    };\n\n\nAh, the _real_ WTF is that it's an Oracle database. That's always a WTF.\n\nBut let's trace through this code.\n\nWe get all of our `Foo` entities. We check for emptiness and then do a `forEach`, which seems to make the empty check superfluous: a `forEach` on an empty list would be a no-op anyway.\n\nWe start a transaction, then check the database: if there are no `Bar` objects that link to `Foo`, then we call into the `barDataService` to find data. If there is, we call into the service _again_ , to see if the `marker` property is not null. If it is, we call into the service _again_ to get the actual data we're putting into the database. Then we close the transaction. If anything goes wrong, we rollback the transaction and chuck an exception up the chain.\n\nThat is _three_ web service calls inside of a database transaction. Three calls which could easily be _one_ , and that call could easily also happen _outside_ of a transaction if you're mindful about confirming your constraints. And of course, because they're _not_ mindful at all, they need to manage the transaction directly, and can't use the `@Transaction` annotation provided by their framework, which would at least cut down on some of the boilerplate.\n\nNow, I'm sure you'll be shocked - _shocked_ - to learn that the webservice is actually a bit flaky, and thus times out from time to time. And this isn't the _only_ batch job running, which means the long-lived transactions cause all sorts of contention and terrible performance across the various batches. _And_ this app doesn't have its connection pool properly configured, so the entire software stack can exhaust all of its database connections surprisingly quickly, causing yet more failures.\n\nThe root of the WTF, of course, is doing this as a batch job. A well engineered application would do everything it could to _not_ create data in the database that isn't referentially sound. There, Sally gives us the one bit of good news:\n\n> My current project will do away with the batch processing altogether, so we can say, \"RIP, transactional wholesale triple caller!\"\n\n[Advertisement] Keep all your packages and Docker containers in one place, scan for vulnerabilities, and control who can access different feeds. ProGet installs in minutes and has a powerful free version with a lot of great features that you can upgrade when ready.Learn more.\n  *[ERP]: Enterprise Resource Planner\n  *[ORM]: Object Relational Mangler",
  "title": "CodeSOD: Find a Bar for This One"
}