Notes by Stephen R. Palmer
Trying new technology is always cool. However, 'because it would be cool' is not a sound basis for electing to use a technology on a project. For example, I have known one small team of developers force a new version of .Net on a major multi-project program purely because they wanted to try out some of the new features in that release. Technology should always be selected on its merits; what advantages/disadvantages are there in using a particular technology. To put it another way; what risk does a specific technology introduce/mitigate in a project?
Oracle's Java Enterprise Edition (J2EE) technology is a set of services and API's aimed squarely at the enterprise information system developer. The .Net frameworks and libraries provide similar capabilities in the Microsoft world. In both cases there are fundamental services that these frameworks provide:
Component technology - building systems by plugging together ready-made components instead of writing every object from scratch - is a goal to which most in the software development world would subscribe.
For components to be pluggable they need to conform to a set of standards. Nothing demonstrates this better than the differences between electrical, electronic and telecommunication standards in different countries. Not only are power and communication sockets and connectors different, voltages, frequencies, protocols and storage formats also differ. For example, without using adapters and converters, a television, video recorder or mobile phone, etc., bought in the USA cannot be used in European countries and vice versa.
Enterprise Java Beans and comparable .Net libraries are just two such set of standards for building software components in enterprise information systems.
Being able to buy off-the-shelf components to implement chunks of an enterprise system reduces development time and cost.
Building your own in-house components that can be reused in multiple systems actually increases initial development time because it requires much more work to design and build a good component than to build a 'good-enough' custom piece of code. The pay back comes only when components are reused in subsequent systems.
Few project managers are rewarded for delivering good components (or even good maintenance documentation :-( ). The success of a component architecture is therefore largely dependent on the production of off-the-shelf components by third parties.
Another success factor is the services provided by the framework into which the components are deployed. These can help reduce the amount of work a developer needs to do to perform common tasks. The EJB specification makes use of numerous standard Java API's to provide a rich set of services to developers. .Net is similar.
Many business systems today use a relational database to store data when it is not in main memory.
There are a number of design issues involved in mapping object oriented information to relational database tables. These include mapping inheritance hierarchies, retrieving collections of objects, managing concurrent transactions and using object identifiers versus primary keys. As a result, a number of significantly different proprietary products exist to help automate the generation of object to relational mappings.
In early versions of JEE, Enterprise Java Beans came in two distinct blends. Entity Beans were the 'data centric' blend because they provide some help in manipulating persistent data. A developer could specify an entity bean as using container managed persistence or bean managed persistence. All entity beans implemented a standard set of persistence-oriented operations. For container managed persistence, the EJB container was responsible for implementing these operations (normally referring to a mapping of attributes to table columns supplied in XML files called deployment descriptors that are packaged with an EJB). Bean managed persistence required the bean's developer to implement the standard operations (normally using Java's JDBC API). Container managed persistence was usually restricted to mapping a bean's attributes to columns in a single database table. i.e. each entity bean represents one row in that table thus avoiding many of the OO to RDBMS mapping issues.
These days the Java Persistence API (JPA) provides a much better object-oriented persistence mechanism for EJBs and reflects the success of proprietary and open-source persistence tools such as Hibernate and TopLink
The .Net world has similarly suffered from weak object-oriented persistence mechanisms like ADO. NHibernate continues to provide a workable alternative here while Microsoft's recent ORM features in Visual Studio slowly mature.
An enterprise system must manage communications between client machines and server applications, between server applications on the same machine and on different machines within an enterprise, and between the servers of multiple enterprises.
EJB's use a number of standard Java API's to provide these
services. The JNDI naming service is used to find remote references
to factory objects used to create, retrieve and delete EJB's. The
factory objects are remote objects implementing an EJB's Home
Interface. The only way to invoke an operation on an EJB is via
it's Remote Interface. Originally, the RMI over IIOP
protocol and
API were used for invoking operations on EJB's via their remote and
home interfaces. Web service protocols are available now.
The implementation of the standard EJB Home and Remote
interfaces pollutes a Problem
Domain class with a large amount of
EJB specific code (yeuch - but most distributed object
architectures do similar things). Much of this is now largely left to
convention, annotations (called attributes in the .Net world) and the
container so there is less clutter in the code.
Remote objects also require
artificially large grain operations to avoid large numbers of
network calls that result in poor performance (yeuch - but again
most distributed object architectures require the same).
Thankfully J2EE provides the JSF/JSP/Servlet API's and services that
are an excellent alternative approach to client/server
communications when menu-driven, form-oriented user interfaces are
sufficient.
In the .Net world, communication between systems is now best
accomplished with the Windows
Communication Framework (WCF). This framework does a good job of
hiding the revolting spaghetti and complexity of XML-based web service
technology from the average developer.
Probably the biggest advantage gained from using EJB's is its
support for declarative transaction management. It is no longer
necessary to program explicit transaction control using fairly
complex API's like OMG's Object Transaction Service, its Java
implementation, JTA,
or your own API. Instead transactional
characteristics of objects are declared in deployment descriptors.
.Net implements exactly the same sort of features and Microsoft's
original MTS
product actually predated JTA and JTS.
Changing transactional behavior no longer requires changes to source code. Objects of the same class can be deployed with different transactional characteristics in different applications. The responsibility for correct transactional behavior now falls to the assembler or deployer of the EJB's instead of the developer. The developer does need to consider how her bean might react with different transaction characteristics and code and test appropriately; adding flexibility always adds to the number of paths that need to be tested.
Declarative transaction management does little to help resolve isolation level and pessimistic vs optimistic locking issues and these capabilities can vary across application servers and databases.
Critical to any set of security services is the ability of the system to establish the identity of a user. End-users of enterprise systems like to have a single-sign-on where they provide confirmation of their identity once. Most enterprise applications however, require a user to identify themselves each time they start the application. This leads to multiple user ids and multiple passwords (with different rules about what makes a good password) per user - inconvenient for the user, a headache for system administrators ... but heaven for that special breed of data security officer that would prefer people did not use a system at all (thus keeping the data completely secure) :-)
Authentication was not originally specified in either the EJB
specification
or the JEE client component specification. This made this area
subject to vendor specifics. These days this are has been standardized
and is a well-established part of the JEE specification.
Authorization is the ability of a system to restrict what each user can see and do.
There are at least three variables in authorization of a nontrivial enterprise application:
User role based security assigns each user to one or more roles. Each role is given specific permissions and/or capabilities. EJB's provide a declarative role-based security mechanism. Each role is granted access to methods of classes by declarations in deployment descriptors. However, method level is often too granular and an administrative headache where multiple methods exist to perform the same operation in slightly different ways. In many cases, a role is allowed to see objects in a class or not, update objects in a class or not and delete objects in a class or not - but this level of granularity is not supported by EJB's.
More complicated security rules depend on whether or not the user owns an object (maybe they created it, or they are assigned to a team that created it). It gets even more complicated when access depends also on the state of the object. For example, once submitted to a manager, an owner may not be able to update their object anymore.
The only support provided by EJB's for this sort of authorization is a container supplied method to inquire if a user belongs to a certain role. Many organizations are looking at business rules engines to help manage these more complex access rules.
Recording who did what and when they did it is a
common requirement within business systems especially where
financial transactions are involved.
JEE has significant logging capabilities defined for it. .Net
developers can use the open-source log4Net software for comparable
features.
A general rule of thumb is, "The more generic a solution, the slower the performance". EJB's are no exception. The overheads of the EJB container services are significant.
Where user numbers and usage patterns benefit from EJB's resource management capabilities this performance overhead may be offset. Specifically, EJB containers may reuse instances from pools of objects to reduce the overhead of creating and destroying objects. An EJB container may also unload (passivate) and reload (activate) beans from/to memory to reduce memory usage. Obviously different vendors EJB containers and servers perform differently making the choice of vendor important (and the pain of switching vendor more likely to be felt).
This has been a very short introduction to each of the
enterprise system services above.
Java's original big claim was 'Write Once, Run Anywhere' and today
it lives up to that claim. However, EJB's originally did not! To run
Enterprise Java Beans, we were required to have an application
server product written by a third party vendor. However, the latest JEE
specifications are so much tighter than the originals and portability
is far better. Despite this
variations between different vendors' JEE containers and
application servers still exist, and anyone who has had to switch
application
server products during development knows that it is not
straightforward.
Where it fits, JEE and .Net technologies are there to be used today but, as always, developers need to continue to pick the right tool for the job.
This article is an updated version of an article first published as CoadLetter #73.