If you’ve ever deployed an EAR with a 12,000-line ejb-jar.xml, you deserve hazard pay.

Developer at wit’s end
When one more JNDI lookup breaks you.

For many of us still maintaining legacy Java EE systems, enterprise Java isn’t about sleek microservices or reactive streams. It’s about @RemoteHome , classloader gymnastics, and figuring out why a bean that compiles cleanly still can’t be looked up at runtime because it wasn’t bound under the “right” flavor of java:global.

We’re not choosing this life — we inherited it. And yes, we could move to Jakarta EE, CDI, and RESTful APIs… but only once we’ve extracted ourselves from the JNDI quicksand without breaking everything.

Exhibit A: The Session Bean You Thought You Modernized

You bravely swap out your EJB 2.1 SessionBean for a nice clean @Stateless bean with @Remote. You deploy. And you get:

java.lang.IllegalStateException: No parser found for http://www.jboss.com/xml/ns/javaee

Why? Because JBoss has opinions about where your beans are declared. Apparently, mixing annotations and jboss-ejb3.xml is like crossing the streams in Ghostbusters.

Multiple JNDI Names? Sure. But Not Without a Fight.

Let’s say your app expects this JNDI name:

java:global/MyEAR/MyJAR/MyBean!com.example.MyRemote

But after migrating to EJB 3, the container decides it’s now:

java:global/MyEAR/my-ejb3-module/MyBean!com.example.MyRemote

Cool. Can you have both? Technically yes — but you’re going to need jboss-ejb3.xml, and no, @Stateless(name=...) won’t help you here.

The CDI Way: Fewer Files, More Sanity

Now imagine a world where:

  • You @Inject what you need
  • You write @ApplicationScoped beans with no ejb-jar.xml
  • You expose services over REST instead of remote interfaces
  • You don’t spend hours diffing JNDI names across modules

That’s CDI + JAX-RS. And it’s glorious.

But Until Then…

Until you get the green light to retire that ancient EAR:

  • Use ejb-jar.xml if you must — but only for beans you haven’t touched in 5 years
  • Let your EJB3 beans live free with annotations — and override JNDI bindings only where absolutely necessary
  • Treat every deleted <ejb-local-ref> as a small act of liberation

Modern Java EE (Jakarta EE) is actually great. But migrating there from a decades-old JBoss 6 stack isn’t just a refactor — it’s an archaeological dig.

Sometimes all you can do is dig carefully, refactor when safe, and quietly mutter “I miss CDI” as you grep through another XML file.