An obvious alternative to EJBs is direct SQL-calls to the database, via JDBC drivers. On the legacy system I was working on some programmers had used direct JDBC calls, some used EJBs. What was the benefit of each approach? It seemed the benefit of using JDBC was simplicity. What was it for EJBs?
I. HOW I CAME HERE
We started a project to upgrade an application from JBoss-4 to a newer version. But rather soon this started to seem a bigger project that we had hoped for, because of the difference in XML-dialects which define the EJBs on JBoss-4, vs. later versions.The XML-definitions should have been backwards compatible of course, but were not. Even though there is an evolving standard for Java EE, all application-servers add their own XML definitions for server-specific configuration of them and EJBs that run on them. The standard itself may have evolved in incompatible ways. Or perhaps a newer JBoss version is enforcing it more strictly. This seemed to be the disadvantage of EJBs.
Trying to start the new JBoss with the old application gave obscure error-messages we couldn't make sense of. Remedies for some errors were found on the web, but other errors remained. And new ones seemed to emerge every time one was solved.
It was unclear not only how to get rid of the error-messages, but also how much time it would take to get rid of all of them. And it is bad to start a project whose duration you can't estimate.
A JBoss installation has two main parts: A web-server which on JBoss-4 is Tomcat, and the "JBoss proper". Both of these are large systems on their own. To understand and tune the whole system you also need to understand how they work together.
Would it be possible to run the system JUST on Tomcat? That would cut (at least) in half the area of expertise needed to maintain and port the system from one platform-version to the next, now and in future.
But if we used only Tomcat we couldn't use EJBs. They only run on 'true application servers', like JBoss, WebSphere, GlassFish, etc. They do not run on 'mere web-servers' like Tomcat.
Did we really need the EJBs? They were used heavily by the application in question, about 100 EJBs in total. Would it be possible to get rid of them and replace them with something simpler?
And only then, after working with EJBs so long I started to see their value. But I also started to see they could be replaced with Plain Old Java Objects (POJOs) - IF we understand why EJBs are needed in the first place. So, after this lengthy but necessary introduction let me try to answer that question.
II. WHAT EJBs DO
There are three main types of EJBs: 1) Session Beans, 2) Entity Beans 3) Message Beans. Rather than describe each on its own, it helps if we can first see what they all have in common, before looking at their differences.What is common to all bean-types? That is the discussion I haven't found in any book or article so far. Which is perhaps the reason it took me so long to understand what they all are about.
Clearly they are all part of the same standard. That is one thing they have in common. They are all programmed in Java AND XML, or alternatively in Java and Java annotations.
But they seem very different in purpose. Session Beans help you deal with user-sessions on the web. Entity Beans help you deal with database interactions. Message Beans help you deal with batch-processing jobs. Is there really any common purpose to them? Were they grouped together simply because we like the word "bean" so much?
Here's the one thing in common about their purpose: All EJBs help implement persistence.
Entity Beans persist your data in the database. Session Beans persist the memory of user actions during a web-session. Message Beans persist tasks the user may initiate during the session, so they can be performed later.
The REASON we need help in persisting things is that web is a stateless protocol. It is just a set of requests and responses. Enterprise Java Beans allow you to implement (the three types of) state on top of the HTTP -protocol.
Example: You read the user's name from the database when they log in. You may need this info several times during the user's session. But you don't want to query the database every time you need it. Entity Beans cache the information in memory when it is first read from the database. The database is queried only once. That allows your application serve a much larger number of simultaneous users than it could otherwise.
Session Beans persist information that can be forgotten after the user-session is over, or that is perhaps saved into the database (via an Entity Bean) once the user commits to their purpose.
Message Beans persist information about what tasks need to be performed later. For instance large numbers of users might input a lot of data into the system, which we want to analyze later when the system is less busy. We may want to run the report-generator once a night.
III. IS THERE A BETTER WAY?
As described in the introduction we had a large number of EJBs in the legacy application, and they seemed to make it practically impossible to port the application to the latest JBoss version.The system contained large number of interactions with these EJB classes, which could not be ported to Tomcat, because the EJB-classes are dynamically generated by JBoss. The exact XML-instructions for generating such 'Proxy classes' were only understood by JBoss-4, not by later versions of it.
But after analyzing how this particular application used EJBs, we realized it was relatively straightforward, although still tedious, to write our own Java classes which would replicate the functions of the EJBs.
Difference was that instead of writing XML to tell JBoss how to create the bean-classes we wrote the bean-classes ourselves. Which made it trivial to understand what they do, how they talk to the database, and how they persist data during the session to avoid unnecessary querying of the database.
The alternative mentioned in the beginning, direct JDBC calls, is still a possibility. But it doesn't take care of the caching aspect. That might mean every programmer takes care of caching in their own way. If instead we give them a common set of POJO-EJB classes (PJBs?) all team-members can take advantage of caching that comes with them. They don't need to know about SQL or the database-schema, they just need to be aware of the PJB -classes provided.
The system now runs on plain Tomcat, and we hope it will perform better because of it. At least Tomcat starts much faster than JBoss. If there are issues, we can always dive deep into the code to see where it could be optimized. It is much simpler to maintain and debug.
IV. SOME ADVICE
My intention here is not to bash EJBs or "app-servers" but to explain what they do. But once you understand what they do it is relatively easy to write something similar yourself, with Plain Old Java Objects (POJOs).Newer versions of the EJB standard allow you to replace XML with Java's @-annotations. If you do that it is more likely your system will run also with future versions of different application servers. You get to keep the Java-code and annotations in the same source-file which makes it easier to understand how they work together.
But annotations are still much like XML. You can only assume their effect is what you think. Is it the same on every app-server (-version)? You can't be 100% sure. Whereas if you write plain Java code yourself, you can always read it and debug it, and SEE what it does.
Avoid using any features specific to your application server, even though that might be tempting at times. It would make it difficult to port to a different but better platform in the future. If you are a project manager it may be hard to control what your programmers do, how tightly they get coupled to a specific app-server. That is one reason to mandate the use of a simpler platform, a plain web-server like Tomcat.
If you opt for a full application server instead, consider compiling the app-server from the source. Then you can at least debug what it's doing, and possibly even fix some bugs yourself.
But be prepared for complexity overload. Application Servers are powerful, complicated, dangerous beasts. It takes a long time to tame your specific tiger. Choosing one over another is a long-term investment which requires continual re-education from you and your team.
© 2014 Panu Viljamaa. All rights reserved
A better alternative would be not to use Spring and JPA?
ReplyDeleteI've tried Spring a bit but not really used it for production so I can't comment on that. From the little exposure I had and it was years ago it seemed to be an XML-based technology as well. What I discovered in my latest EJB projects was that I find plain old Java objects much more useful than XML. But that was really intended as a side-note in my article. The main intended point was to give an answer to what are the main benefits of EJBs - or something like them, as well as to encourage discussion about that
DeleteInteresting article. Just some extra notes: Session EJBs are not necessarily stateful; as a matter of fact a lot of people advocate against using stateful EJBs.
ReplyDeleteAlso, it's not mutually exclusive to use JDBC OR entity beans..
Some other features of EJBs that I think is important, especially if you run in a managed container, is transactions, JNDI lookup and pooling. This means you can hook up your EJB + persistence mechanism of choice (e.g. myBatis) and your transactions are taken care of via the EJB. It also means you can essentially see EJBs as components or reusable 'services'/building blocks.
For all the above you can do it yourself using Pojos, but if you're running in a JEE container, why not take advantage and leverage its features? Spring is a good alternative if you're running on let's say Tomcat and don't want to/have to use JEE or you like the DIY approach.
For this particular project it seemed we didn't need any of the more advanced features of the J2EE standard. If a simpler system like Tomcat is all you need then I think it's a better way to go, especially for smaller teams and projects. For larger teams I'm sure it makes sense to invest in the expertise for systems like JBoss that support all of J2EE.
DeleteThis article is very misguided and outdated. Modern application servers are very lightweight and modular, wildfly for example load modules only when they are used and starts up in a second (glassfish takes a couple of seconds). Annotate ejbs have been around for 8 years!!
ReplyDeleteWe tried WildFly and it would have worked as well. But a simpler system like latest Tomcats seemed to be all we needed, so we took that route. Again I can't really comment on if WildFly might have been a better choice since we didn't thoroughtly try it out - we didn't have the time for that. Just my feeling that if you are not sure what is the better choice, it's best to choose the simpler one.
DeleteWhile this article has good intentions, it is really quite horribly out of date. Instead of being focused on modern POJO programming paradigms that have long since been proven, it is focused on a point of view based on EJB 2. For perspective, EJB 2 was last released in 2003 - now an 11-year old technology that lived alongside COM/DCOM and Windows 2000. It refers to EJB 3 as "newer technology". EJB 3 was first released in 2006, not to mention JPA. The last release of JBoss 4 was in 2008 and it is no longer actively maintained by Red Hat (which is why I am guessing the upgrade effort mentioned took place).
ReplyDeleteYou are right that my article is much about what to do with legacy technology, like applications that run on JBoss4. But as I said the main point that interested me was why we need EJBs in the first place,. I hope the article gave some answers to that. Whether it's better to use an existing "advanced" platform like the latest JBoss, or a simpler one like Tomcat + POJOs is a decision that should be made on a project-by-project basis of course.
DeleteThanks for comments everyone. I'll appreciate all and more comments on especially why you find EJBs useful in practice, What is the main reason we need them? Why (sometimes) they are the best way to go instead of some simpler technology like direct JDBC calls for instance.
ReplyDelete