The specs are very clear. When you get an EJB Home object from the naming service, or when you get an EJB Remote reference back from a finder method in an Enumeration or Collection, you can't immediately cast it to the type you are expecting, you must first pass it through the PortableRemoteObject.narrow() method. This has something to do with IIOP, I believe.
I'm left with only one question. Why in the nine layers of Hell should I care about this CORBA shite?
Why didn't the writers of this spec take that tiny step back and think “OK, they're writing this in Java, so we should obey simple Java casting semantics”. PortableRemoteObject.narrow() was the first step in my steady, and now complete disillusionment in Enterprise JavaBeans. The first time I saw it, even though I was a relative newcomer to OO modeling at the time, something clicked in my head, something said to me this is so very, very wrong.
A part of me is convinced that the only reason there's so much CORBA stuff tied to the EJB spec is because IBM was one of the big backers of J2EE, and WebSphere Application Server was built on top of Component Broker, their CORBA ORB. (Understanding this fact is a crucial step towards understanding some of Websphere's more weird behaviours)1
PortableRemoteObject can bite me.
Update: From the comments so far, it seems I was a trifle too flippant. Yes, I know the technical reasons that a CORBA object needs to be explicitly narrowed. An EJB, however, is not a CORBA object. It's an Enterprise JavaBean. It may be implemented as a layer on top of CORBA, and may be implemented in such a way that CORBA clients can talk to it. But when I'm talking to it in pure Java, I don't care how it's implemented under the hood, and I don't want to care.
What I object to is that even if one accepts that EJB is a Java layer on top of CORBA, I would expect that Java layer to hide the CORBA implementation details, and expose EJBs to me in the idioms of the Java language. If I wanted to talk CORBA to the damned things, Java comes with a perfectly good CORBA API that I can use.
1 Disclaimer: My employer is an IBM Business Partner. Websphere pays my rent. As such, the above is obviously said in the context of a deep and abiding affection for the product. ;)
Well, when using IIOP, what goes over the wire needs to be compliant in order for it to work regardless of languages. When transferring your data with RMI over IIOP you cannot know on one end if it actually IS java on the other end, so that means:
* No non-serializable stuff can be sent
* No non-remote exceptions can be thrown
* Casting to java objects cannot be done directly
Local interfaces solve some of this, and using local interfaces you CAN actually cast directly, since you don't have to talk IIOP.
Doing the pure java thing remotely would require us to write something specific for java, and not make use of the vast amount of work put into CORBA...
...but I agree that it is a bit tedious to do this all the time. Put the narrow stuff in a utility method, and you're done.
I was being slightly flippant. I do know the technical reasons that, at some point, the remote object needs to be narrowed. My beef is with the fact that it was deemed somehow necessary that this be done manually by the client code.
When I'm using a Java API to access Enterprise _Java_Beans, there's no mistaking the fact I'm writing in Java. As such, the API should take care of completely hiding these irrelevant CORBA-isms from me.
Corba does support languages that do *not* support casting. Therefore Corba does not support stubs that support multiple interfaces. Therefore you cannot simply cast Corba stubs.
One open question might be, whether the Corba java language mapping didn't support stubs with multiple interfaces.
Sure, but you (the client) don't actually know that you're talking to an EJB or a CORBA object. This information just isn't on the client side.
Still not convinced. Like I said, I know the technical reasons that CORBA objects need to be explicitly cast somewhere. What I object to is that somewhere being in _my_ code.
So the underlying glue is CORBA. So what? I'm programming Enterprise JavaBeans in Java. Why do they make me do more work by exposing this annoying, inconsequential implementation detail to me?
This is my essential objection to all of the EJB mess. At every level, it makes me do more work than I should have to, and constrains me to a programming structure that makes even the simplest operation mind-numbingly complex.
Writing an EJB-based application is too much, and too often an exercise in in a pumping out boiler-plate procedural code.
Well, I agree that to some extent the underlying stuff should be hidden more to the end developer. However, a lot of work _was_ actually put into abstracting the corba specifics into basically a single narrow() call. Being able to cast directly in java without rewriting the transport specifically to support java without compilation errors would require byte code modifications which are not impossible, but perhaps a bit tricky for such a "small" gain.
Not having to pass the interface to narrow() sounds good in theory (I used to think the same thing), but how do you expect to pull it off? We're looking up a CORBA stub from the CORBA naming service. Maybe we don't even have the Java interface to go with it. Does the underlying implementation eat the exception and move on? What if we thought we had the interface and now it eats the exception and goes on? We should probably specify whether or not we want it to wrap the CORBA stub with the typed delegate. Well now we might as well narrow it ourselves. I guess we could maybe derive the Java interface name from the CORBA interface name (which would be the EJB remote interface). But, what if we don't have the EJB interface deployed to the client and we simply want to use an interface that the the EJB remote interface inherits from? This is really just using RMI IIOP. Should RMI IIOP lookups always try to find a suitable Java interface? What if what we're looking up isn't Java on the other end. I guess we could eat the exception again and return the CORBA stub.
We could put an EJB client-specific layer over JNDI, but why? To remove one or two lines of code out of our entire application (assuming you have the narrowing relegated to a generic method in a service locator)?
I disagree with your update; you were exactly the right amount of flippant.
The client doesn't know that CORBA is involved, and damn well doesn't want to. If PortableRemoteObject.narrow() is the greatest technological invention since the bread slicing machine, and hides all the hairy CORBA-specific details, I'm happy for the EJB container to call it as many times as it needs to be called. I'd be thrilled, really.
But if it's something that as the user of the EJB container I have to call every single time I pull an object out of a hat, it's not an "EJB client specific" piece of code that's needed, nor is it relevant that it's only "one or two lines of code". It's one or two lines of CORBA-specific code, so those two lines should be in the code that's dealing with CORBA.
A fundamentalist neighbor kid gave me a book of this ilk as a birthday present when I was about six. Among other things, it explained at great length that the big empty spaces in crested hadrosaur skulls were combustion chambers for a hydrogen peroxide / hydroquinone reaction (along the lines of the one used by the bombardier beetle), thus giving rise to the popular legend of the fire-breathing dragon. Some nice pictures, but none of Saint George and the Parasaurolophus, unfortunately.
Search Google http://www.google.com/