Is JavaEE really portable?
Asked Answered
O

4

3

I'm just implementing a JavaEE assignment I was given on an interview.

I have some prior experience with EJB, but nothing related to JMS and MDBs. So here's what I find through the numerous examples:

  • application servers bind their topics and queues to different JNDI names - for example topic/queue, jms
  • the activationConfig property is required on JBoss, while in the Sun tutorial it is not.
  • after starting my application, jboss warns me that my topic isn't bound (it isn't actually - I haven't bound it, but I expect it to be bound automatically - in fact, in an example for JBoss 4.0 automatic binding does seem to happen). A suggested solution is to map it in some jboss files or even use jboss-specific annotations.

This might be just JBoss, but since it is certified to implement to spec, it appears the spec doesn't specify these these things. And there all the alleged portability vanishes.

So I wonder - how come it is claimed that JavaEE is portable and you can take an ear and deploy it on another application server and it magically runs, if such extremely basic things don't appear to be portable at all.

P.S. sorry for the rant, but I'm assume I might be doing/getting something wrong, so state your opinions.

Ophelia answered 25/4, 2010 at 7:33 Comment(0)
T
7

Java EE, like (almost?) any standard, is something that implementers strive to advertise adherence to but desperately don't want to adhere to.

Consider this question: how does Red hat make money? By giving things away or by selling them? If the code you wrote could be easily transferred to another Java EE application server, this would interfere with them making money from you. The solution to this is the venerable "embrace and extend" technique that has been attributed to Microsoft but in reality has been the tool of choice for commercial software vendors since the first standard was published.

If you stick strictly to the Java EE APIs in your code then JBoss (or Geronimo (or JonAS (or ...))) will run it as well as any other compliant application server with the only changes being required in the server-specific deployment descriptors. This is the embrace stage.

Each server -- the commercial ones (like JBoss) in particular! -- also tends to add extra stuff to the API to "make things easier". (To be fair these often do make things easier.) Developers -- especially those not intimately familiar with the standard APIs -- frequently fall into the trap of relying on these extra APIs without wrapping them in any way, thus allowing these extensions to inundate their code to the point that they're difficult to remove should you wish to change platforms. This is the extend stage.

Name a standard from any point in software history and you'll find people embracing and extending (to the point that when people talk about "deadly embrace" I have to forcibly move my thoughts away from vendor lock-in problems to the proper terminology). You'll also find end-users (developer or otherwise) falling for it. Java EE is no different than any other technology in this regard.

Then you factor in just how badly-worded most specifications are and ...

Trinatte answered 25/4, 2010 at 7:33 Comment(3)
Actually, the sheer ability to be able to get away from it, might be a very good reason to stay with it :)Generalization
Then again you also have people don't even complete the standard but they still extend it.Jd
Well, yeah. Those tick me off even more than the embrace and extend folk.Trinatte
H
2

Joel says "all non-trivial abstractions are, to some degree, leaky." I have found this to be very applicable to JavaEE. Consider that a JMS exception may be something transient such as a full queue. This is a typical fast-producer/slow-consumer problem and ideally the producer will throttle down to match the consumer's speed. But the error may also be fatal such as an authorization failure. In the first case retries eventually succeed (usually) whereas in the second case no amount of retry will help until humans intervene to fix the authorization failure.

So what do you do in your portable program to address this? One approach is to treat every JMS exception as fatal. Close all your objects and reinitialize the program. Sort of like killing a fly with a sledgehammer but very portable. Alternatively, you can check the JMS exception to see if it's a transient or fatal error and take some appropriate action. This is much more efficient but since the JMS exceptions are provider-specific it is hardly portable. Some of my clients have taken the approach of writing vendor-specific shims which catch JMS exceptions and do vendor-appropriate things with them so that the code can be "portable" (think: software equivalent of the Hardware Abstraction Layer).

And of course, this is just exception handling. Similar issues exist across the board. Consider reconnection details. Some transports bubble up a connection failure to the application or container. Some hide it away with the idea that the code should not need to know about this. But the reality is that virtually all messaging applications will need to provide an alert or log entry if the network is permanently down. You would not want the app to just hang forever if the network failed, right? So ultimately even an app running on a transport that provides transparent reconnect needs to code for connection failures. The specific features and behavior of the transport provider will leak up through the abstraction of JMS.

For my money, JavaEE makes the skills portable across transport providers. The application needs to be aware enough of the underlying transport provider to deal with the abstractions that bubble up to the surface. To the extent that you can avoid the leaks the app is portable, but no further.

Hustings answered 25/4, 2010 at 7:33 Comment(1)
+1 for the "more portable skills" thing. That is, historically, the main benefit of any standard since nobody ever actually adheres to standards.Trinatte
I
1

That's just a partial answer but Java EE 6, more precisely EJB 3.1, finally specifies Portable Global JNDI Names. Prior to Java EE 6, JNDI naming wasn't standardized and each app server vendor was using its own rules which was indeed bad for portability (a kind of vendor lock in). Consequently, in the J2EE 1.4 world, if you wanted to ease the portability of your enterprise application it was necessary to implement various strategies, typically in your ServiceLocator class. The introduction of dependency injection in Java EE 5 reduced the need for lookups and somehow "improved" the portability but still, no standard for when JNDI lookups are needed and polyglot ServiceLocator are still required.

Intermingle answered 25/4, 2010 at 7:33 Comment(0)
F
0

The core EE application can run unchanged. The external configuration is application server specific.

Flabellate answered 25/4, 2010 at 7:33 Comment(2)
as I noted, this is extremely basic, core JavaEE - an MDB and an EJB that's sending messages to a Topic.Ophelia
Basically if you have a string varying on the application server, you specify its value externally (in JNDI), or in the application specific configuration file. Any "where can this be found" string is - unless explicitly specified in the specification - such a value.Generalization

© 2022 - 2024 — McMap. All rights reserved.