Warning, rambling ahead.|
Indeed languages are fairly standardized, and J2EE is also standardized. In fact I think it has done better than other attempts to produce a standard with multiple implementations.
Some of the possibility for lockin comes from the "low" level of the J2EE spec, at least in terms of getting business function implemented. Here's where the design patterns prove useful, they make it easy to rewrite the same code as everyone else to implement the same features. Of course, a vendor could provide an implementation of these patterns, and that's what many of these frameworks are, but the temptation to use this as a way to try to lock developers into their platform is possibly too great to resist.
It is possible to write cross app server code, at work we develop for WebSphere and WebLogic, but it's much more painful that sticking to one. We only do it because we have to sell our software on both platforms. If we were an inhouse effort them we'd go with whoever provided the most productive set of development tools, and probably pay lip service, but not much more, to portability.
These days open source probably has some impact of code standardization. If you release code, or download code, you want it to run on multiple platforms, so you put some effort into portability. On the other hand you probably reinvent the wheel many times in an attempt to remove dependence on other libraries. That's where efforts like jakarta in the java area have impact. By bringing together many java projects they can promote code reuse.