HumbleBlogger

Saturday, April 30, 2005

ASP.NET vs J2EE

About two years ago I attempted to use ASP.NET for a project, but after that project was concluded - and due to experiences encountered - I abandoned using ASP.NET and have been using J2EE for middle-tier development ever since.

Here is a run down of some of the troublesome issues I ran into:

I didn't like having to use IIS nor the fact that ASP.NET runs in its own separate process - security models and process/thread permissions get more complicated to configure. IIS has its own security settings, user account and process permissions, and then ASP.NET runs in a separate process with its own user account as well. Because my corporate network environment is very locked down in terms of user permissions, this caused me a never ceasing source of grief and difficulty to sleuth out these headaches.
The normal posture at our company is to not let individuals run IIS on their computer because of it being a target for security attacks. I had to get special domain permissions set up so that I could run IIS on my own computer for development purposes. This did not thereafter make matters trouble free for me, though. I continued to relentlessly struggle against IIS vs ASP.NET permissions configuration headaches, and when I threw in an Oracle OLEDB driver that needed to be used, I got pummeled with yet another very thorny permissions problem that took several days to sleuth.

After all that, all I could muster ASP.NET to do is to be enabled so as to program some code that responds to HTTP request and/or implements web service calls. Well, what I really wanted, though, is to be able to implement a distributed application that uses messaging. However, with Microsoft, that involves licensing and setting up an MSMQ messaging server. MSMQ is a Microsoft proprietary legacy messaging service which was built by their dev group in Israel. (Microsoft does a very poor job of supporting MSMQ with respect to non-Windows platforms - basically leaving one to resort to a scattering of third party products where yet still more licensing cost would have to be incurred.) Because it is a legacy system, to use it from .NET implemented managed code means working through a layer of .NET wrapper classes that Microsoft provides. To top it off, ASP.NET has no intrinsic container-like architecture for hosting components that participate in messaging.

Now .NET Remoting would be an alternative to ASP.NET web services. But unless you roll a standalone .NET Remoting server application (with all of the reinventing of the wheel that that entails), then you still get the convoluted solution pathway that involves the IIS process coupled to the ASP.NET process.

Neither .NET web services or .NET Remoting are messaging style solutions but are just another dressed up RPC (with tons of marketing hype behind them - particularly web services). In the Microsoft camp, one will have to await project Indigo to deliver a managed-code implementation that has messaging capabilities. Now these RPC-style protocols have significant draw backs when being used to build distributed applications: There is high coupling between end-points (they have to know about each other directly); there is no queued behavior of the data traffic; nor a publish and subscribe feature; nor a server-side push notification capability (although with a persistent .NET Remoting connection one might concoct something - but would have to explicitly implement the fan-out of one publisher publishing to potentially many subscribers).

Microsoft does provide the ability for both .NET Remoting and web services clients to do asynchronous calls, but there is no queuing on the server-side so you can't count on a coherent ordering for the processing of request. A client's given async call could end up getting processed ahead of another in a manner that is chronologically out of order. Also, with async-style RPC there's no equivalent to message persistence - which when message persistence is coupled with transaction semantics, it enables messages to be reliably processed (think credit card transactions, etc).

Obviously with .NET Remoting or .NET web services there is no such thing as being able to bridge message traffic or route message traffic based on things such as message properties. One can write filters that can peek at messages before the normal code sees the payload, but these are crude to make use of relative to, say, the Java JMS message filtering approach. Yet with true messaging solutions, message traffic, selectively filtered, can be asynchronously bridged to other queues and thus other message consumers for, say, diagnostic or archiving purposes. (I've used this technique to test software that is under development against actual real-world production message flows - because of message bridging capabilities I could do so transparently in conjunction to the production environment. My program under development could process in parallel to the actual production system in a phantom-like manner. This kind of capability is extraordinarily useful. RPC is stone age computing technology - messaging is 21st century.)

In the particular project where I attempted to use ASP.NET, my clients were wireless WinCE devices running .NET Compact Framework. Consequently I was stuck with having to use .NET web services. Because that is implemented as an HTTP-based protocol - where the client connects, does an operation, closes the connection, and goes away - I had no means of server-push notification or publish/subscribe dissemination of events. (One could resort to UDP broadcast of events but then will get into subnet concerns, etc. That will be yet more hacking and reinventing of the wheel for what should be an off-the-shelf capability. Another technique is to open a persistent database connection and wait on a table trigger event. Such heavy weight connections are problematic for wireless client apps running on WinCE.)

J2EE to the rescue:

J2EE, on the other hand, has JMS as an intrinsic messaging API - which must be supported by a compliant J2EE app server - and the EJB 2.x spec has the EJB variant called the message-driven-bean (MDB). Consequently J2EE app servers come out of the box with intrinsic facilities for building distributed applications on a foundation of true messaging.

Unlike the shotgun wedding of the IIS process coupled to ASP.NET process, everything that I program to in the J2EE spec runs within the same operating system process. (In actuality I happen to use a Tibco JMS messaging solution which runs in its own process - but the integration of Tibco into my J2EE app server is such that this fact is completely transparent to my Java EJB code.) Consequently I never have permissions configuration headaches the way I chronically had to deal with in the .NET/Windows universe. The security and permissions model is vastly easier to contend with.

For my Java development I routinely have used solutions such as Hibernate ORM persistence. (Only recently has Hibernate been ported to .NET.) Instead of data transfer objects coupled with entity beans, I just use plain java objects to fulfill both roles as ORM persistence easily facilitates doing such. In ASP.NET there is the ADO.NET data set. Not exactly object oriented to where your OOP-centric object graphs and entities can be one and the same. Nor are ADO.NET data sets truly suitable as data transfer objects (the objects I shove around via messaging). Its not good to so tightly couple client code to entity structure. (Microsoft has for years now foisted such undesirable tight coupling, though, due to their fundamental approach to data persistence - which they show now sign of relenting from.)

I routinely use XA where my EJBs are doing messaging and also interacting with a JDBC resource (either directly or indirectly via an ORM layer). For J2EE EJB this is done with simple declarative statements in the XML config files of the EJBs. With .NET I'd have no XA support for doing messaging and database persistence coupled in the same transaction because there's no comprehensive app server architecture for hosting such. Instead of relying on ASP.NET to provide XA capabilities via an integrated distributed transaction manager, one has to resort to COM+ MTS - yet another Microsoft legacy system that has not been re-implemented as managed code. (MSMQ, COM+ MTS, and the lack of a managed code ORM persistence service, are all visceral illustrations of how .NET was conceptually delivered into the world as still born.)

My distributed apps frequently employ JMX mbeans to do hardware device control - where they are hosted in the J2EE app server. By being hosted in the app server they can readily provide service interactions to my EJBs and also avail themselves of all the various standard J2EE capabilities. Again, ASP.NET has no provision for hosting such open-ended components - one would have to run them in a separate, dedicated server process (that one rolls oneself) where communication with other ASP.NET-hosted components would all be inter-process in character. Oh yeah - JMX mbeans make it easy to add management interfaces to applications hosted in J2EE - which is of course their intended purpose. There is nothing comparable to the JMX mbean for ASP.NET. The beans I write for J2EE are split about 50-50 between EJBs and JMX mbeans. The JMX mbean is a very useful adjunct to EJB.

In my last significant project I used a rather nice distributed cache solution that is available for my J2EE app server. It likewise supports XA. This cache turned out to be an ideal solution to a issue that this project had to address. My future projects will be leaning more and more on making use of a distributed cache. The advent of 64-bit computing and JVMs that run in 64-bit mode is going to open the door to doing some radically new things with distributed caching. There is nothing out of the box to do something comparable with ASP.NET.

In the future we'll also be looking to adopt a BPM engine - there are scads of them to choose from that can be dropped into a J2EE app server.

My problem domain is such that I don't have to worry so much with scaling of the middle-tier, but I do have to support high availability. Hence for production my J2EE app server is indeed running in a cluster. All my applications that are deployed are designed to run in a cluster configuration (hence the value of such things as a distributed cache). My J2EE app server makes building cluster-capable applications a simple matter. Even my device control JMX mbeans support high availability where they are automatically managed to run as a singleton in the cluster. With ASP.NET one has to resort to the Windows OS to provide some capabilities to enable running web services and such in a cluster. (In contrast, my Java-facilitated clustering capabilities work regardless of whether I'm using Windows or Linux/Unix for the operating system.) There is no .NET distributed cache service per se - one can buy third party products for this, but be careful to nail down the matter of whether such a product can support XA under COM+ MTS - otherwise, what's the point?

So do you see the repeating pattern with Microsoft? You have to bring in: their MSMQ server product for messaging (and be left with very poor heterogeneous platform support options); their IIS web server for front-ending anything using HTTP/HTTPS; COM+ MTS for XA management; Windows 2003 Server for clustering features; ASP.NET for running components written in managed code, and resort to some third party product if you want a distributed cache. In the Java universe we can easily get all we need in a single J2EE application server product - with perhaps a service or two provided from elsewhere such as external JMS or JNDI/LDAP.

Now in recent months my product support organization has made the decision to move our middle-tier applications to be hosted on Linux servers. It has been a breeze to move my Java J2EE stuff over from Windows to a Linux platform. Obviously this would not have been a viable option with a .NET middle-tier approach. Maybe some companies are okay with IT decisions that lead to intentional platform lock-in - myself, I regard such as irresponsible and essentially being cavalier with stock holder investment. I suppose I see that as the biggest negative of all regarding .NET technologies. Unlike Sun, Microsoft has made no earnest effort to make .NET truly OS platform agnostic (you don't see Microsoft themselves actively porting .NET to Linux, Unix, or Mac OS X - yet Java runs on those and even on AS/400).


IBM's AS/400 server rocks the house in two Java benchmarks


As one can see, real world distributed software systems cannot be built without availing oneself of all manner of Microsoft Windows-specific legacy systems. And in going down that path there will be many compromises, frustrations, and outright integration problems to overcome. Alternatively, in the Java universe Java is effectively its own platform rendering the underlying OS secondary. So with a single J2EE app server acquisition one can get just about all that you need. Then there's the various Java IDEs and open source development tools that provide a rich development-side infrastructure.

Jettisoning ASP.NET while adopting J2EE for middle-tier development is one of the best decisions I've made in my career from both a business point of view and a software developer's perspective.