TomcatExpert

How To Migrate JEE Applications to Apache Tomcat

posted by avanabs on July 7, 2010 05:42 AM

I’ve been sharing some thoughts about what’s become a significant trend in many IT organizations, and in particular with my clients…converting Java applications from JEE Application Servers to Tomcat, and more typically Tomcat+add-ons.

Many IT organizations are re-thinking their commitment to commercial JEE Application Servers, due to both challenging business environments that drive the need for more cost effective application architectures and the need to transition to more responsive/agile applications development. When IT organizations talk about “migrating” their applications, I’ve noted that they generally are focusing on one or more of three distinct situations. These are:

  • Moving existing applications (or slices of applications) off of JEE servers and onto lightweight, modular, horizontally scalable container infrastructures
  • Expanding access to existing JEE applications by adding services layers in lightweight containers.
  • Transitioning new development away from JEE application servers and focusing on light weight containers

I’ve been focusing on the migration of existing JEE applications to the most popular of the light weight containers, Tomcat. There are many excellent reasons to consider moving applications off of the commercial JEE servers sold by Oracle/BEA, IBM, etc. While we are focusing on the migration process, many of the business and technical decision factors apply equally well to the second and third situations.

This time, I will be discussing the technologies involved in migrating JEE application code from commercial JEE servers to Tomcat. I’d like to thank the kind (and very expert) folks at SpringSource, as well as a number of other friends around the industry, for their valuable insight regarding the technologies involved. Any errors (and opinions) are mine alone. Additionally, some of the material draws on information published by SpringSource and other open source materials found on the internet.

Java EE API Support

The Java EE specification is quite complex and it also includes a significant number of Java Optional Packages. For each package, the specification defines the version for environments that support a full-stack Java EE 5.0 environment…IE JEE Application Servers.

Note: I assert that Tomcat IS an application server, although it IS NOT a “JEE Application Server”. This is both a strength (by design, it leaves out tons of stuff we rarely use anyway and the needless cost/weight/complexity) and a weakness (it lacks some frequently used services and most administrative capabilities). That said, I’d much rather start with a rock solid, performant, base and then add what I need, rather than dealing with the cost/weight/cpomplexity of the JEE Application Servers..

A Tomcat environment provides access to most of these APIs as a standard capability, by enabling you to “drop in” standard implementation JARs to the Tomcat lib directory, or by bundling the standard implementation JARs with the deployed applications. In some cases, excellent commercial alternatives also exist. In my clients experience, a very large portion (80%+) of their applications require only Tomcat and a fairly small number of add-on’s/drop-in’s.

It is a definite advantage of the Tomcat environment that many of these JEE packages are not embedded out-of-the-box. This is because, as previously noted, most applications only utilize a small portion of the JEE standard and even less of the WLS/WAS proprietary functionality. You can add needed services to the environment fairly easily, in “drop-in” fashion, which means you run the latest version of the specifications and you significantly reduce server bloat (from nearly a GB to tens of MB) by bringing in only needed services and capabilities. Additionally, you can choose among multiple providers, and server operators and application deployers can decide whether to add a package as a standard server feature (by dropping it into the server lib directory), or to embed it in each application.

The following table summarizes the availability of the Java Optional Packages defined by Java EE 5.0 in the Tomcat environment. These are in the same order as Table EE.6-1 in the Java EE 5.0 specification document.

Java EE API Support

Tomcat

EJB 2.1 and 3.0

Client access only.

No support for running EJBs themselves.

Servlet 2.5

Standard.

Java Server Pages (JSP) 2.1

Standard.

JavaMail 1.4

Drop in standard JAR to Tomcat lib directory or embed in applications.

JMS 1.1

Client: Drop in standard JAR.

Server: No embedded implementation.

Multiple third-party (open-source or commercial) products available to run alongside or embedded.

JTA 1.1

No embedded implementation.

Plug-in external JTA provider if needed.

JAF 1.1

Drop in standard JAR to Tomcat lib directory or embed in applications.

Connector 1.5

Not supported.

Web Services 1.2

Drop in standard or third-party JAR.

Multiple open-source and commercial implementations available.

Add JARs to Tomcat lib directory or embed in applications.

JAX-RPC 1.1

Drop in standard or third-party JAR.

Multiple open-source and commercial implementations available.

Add JARs to Tomcat lib directory or embed in applications.

JAX-WS 2.0

Drop in standard or third-party JAR.

Multiple open-source and commercial implementations available.

Add JARs to Tomcat lib directory or embed in applications.

JAXB 2.0

Drop in standard JAR.

Add standard JAR to Tomcat lib directory or embed in applications.

SAAJ 1.3

Drop in standard JAR to Tomcat lib directory or embed in applications.

JAXR 1.0

Drop in standard JAR to Tomcat lib directory or embed in applications.

Java EE Management 1.1

Not supported.

Java EE Deployment 1.2

Not supported.

JACC 1.1

Not supported.

JSP Debugging 1.0

Standard 

JSTL 1.2

Standard,

Web Services Metadata 2.0

Drop in standard JAR to Tomcat lib directory or embed in applications.

JSF 1.2

Drop in standard or third-party JAR.

Multiple open-source and commercial implementations available.

Add JARs to Tomcat lib directory or embed in applications.

Common Annotations 1.0

Standard.

Supported in Servlets per specification.

StAX 1.0

Drop in standard or third-party JAR.

Multiple open-source and commercial implementations available.

Add JARs to Tomcat lib directory or embed in applications.

Java Persistence 1.0

Standard or third-party drop-in, including updated 2.0 spec.

Multiple open-source and commercial implementations available.

Add JARs to Tomcat lib directory or embed in applications

 

Code Migration Strategies

In the sections that follow, I’ll take a look at various aspects of the code migration process, including layers, transactions, EJBs, remoting, data sources, security, messaging, and management.

Layering and Interfaces

A properly layered, interface-driven, and decoupled architecture that uses inversion of control and dependency injection patterns offers tangible benefits:

  • Reduced code coupling
  • Reduced complexity
  • Easier and enhanced testing
  • Increased agility

These benefits dramatically facilitate code refactoring, although care should also be taken to avoid un-necessary “creeping elegance”. It’s all too easy to get tangled up in what can amount to a complete re-write, while the objective (and budget) may be much more modest.

An existing architecture that is not adequately layered and interface-based requires additional refactoring to make it so. So, consider whether this additional refactoring, above and beyond what is immediately needed for the migration effort, will pay off in future ongoing maintenance and enhancement of the application.

Migrating Significant Code-Level Changes Piece-by-Piece

If you need to migrate code-level changes, consider refactoring and migrating piece-by- piece instead of in a “big bang” process, as this is generally less disruptive and more manageable. You can work in multiple iterations, possibly with working code between iterations, until all refactoring is completed.

Where migration involves refactoring away from technology that is not available in Tomcat, with the goal of working code at the end of each iteration, the migration effort should remain in the JEE Application Server until those technologies are completely refactored. For example, consider an existing application that implements business services as session EJBs, currently running in a full-stack Java EE environment, that are being refactored to execute in a Tomcat environment. Migration in pieces allows only a subset of the EJBs to be refactored in each iteration (to POJO implementations of those services, for example…or to an appropriate framework). Of course, if the goal is to test working code between each iteration (a VERY good practice, and particularly suited to agile development environments), this implies staying in the JEE Application Server until all the EJB’s are refactored.

Migration in pieces usually requires one of two strategies: migration by vertical slice, or migration by layer. In the migration by vertical slice approach, a complete “vertical slice” encompassing multiple layers (services, data access, domain, and so on) often representing a logical application component, is migrated in one iteration. Over multiple iterations, code gradually moves from legacy vertical slices to migrated vertical slices. In the migration by layer approach, code is migrated a layer (for example, certain application serevices) at a time. The decision to use a migration by vertical slice or migration by layer approach is application-specific and depends on existing architecture and existing code coupling. It also depends strongly on team preference and standard prqactices. In both cases, the idea is to perform refactoring in manageable chunks.

Service Layer Migration Strategy

Many larger JEE applications have a distinct set of functionality that implements a service or application layer. This code implements use cases, or functionality, specific to the particular application. In best-practice fashion, this layer typically is hidden behind use case-specific interfaces, and it often interacts with a data access layer (by interface), and with domain objects or data transfer objects. In those applications that do use EJBs, it is fairly typical for the service layer to be implemented as EJBs. Additionally, both transactions and method level security are usually implemented in the service layer.

Where a more than minimal refactoring effort is required in the service layer anyway, consider whether to expense potentially additional effort towards effecting a properly layered and interface based codebase. This effort may pay off in the migration effort itself and/or in subsequent maintenance costs.

Data Access Layer and Data Access Objects

Many larger Java applications have a distinct set of functionality that implements a data-access layer, to the extent that this code is responsible for persisting data transfer objects or domain objects to one or more datastores. Typically, code in this layer is hidden behind a set of interfaces that abstract the exact persistence technology in use.

However, in practice, it is not practical to try to abstract away the use of lower level persistence technology such as JDBC, as opposed to higher level technology such as object-relational mapping (ORM). Code in this layer is also often referred to as data-access objects (DAOs). Where data access functionality is implemented through entity EJBs, it is necessary to migrate this code.

Migrating Web and Presentation Layer Code

Migration from JEE Application Servers to Tomcat does not normally entail significant refactoring of web tier or presentation layer code, because Tomcat was the reference implementation for this portion of the JEE standard and/or is the actual implementation within some JEE Applications ervers. In many cases, web tier code can remain almost untouched.

Areas that may require refactoring are related to EJB access and to remoting. Where web tier code is a client of EJB services, and is directly performing EJB stub lookup, a straightforward conversion process to the use of plain Java services may be required. Where code is using EJB remoting, and continued use of remoting is actually necessary, refactoring to an alternate remoting technology is necessary.

Migrating Transactional Code

Before migrating existing transactional code to a Tomcat environment, it is important to understand the options available in a Tomcat environment for demarcating and driving transactions in application code.

  • Local resource transaction APIs: Transactions are driven through the appropriate local resource transaction APIs on local resources such as the JDBC Connection object, JPA's EntityManager, Hibernate's Session, or equivalent.
  • JTA (Java Transaction API): Tomcat out-of-the box does not include a transaction manager implementation that supports JTA APIs. However, you can plug in a third-party external JTA transaction manager (such as Atomikos) to the Tomcat environment to support JTA APIs. Because a third-party JTA transaction manager is an additional component that must be obtained, supported, and possibly licensed, examine the desirability of this approach against the alternative of refactoring code away from the use of JTA.

Although application-specific code may drive transactions toward using these APIs, it is also common for application code to utilize a third-party abstraction layer, which itself talks to these APIs. As an example, the Spring Framework offers transaction functionality, which allows both a declarative and programmatic approach to transaction demarcation, and which abstracts the distinction between JTA and local resource transactions.

JTA: Non-EJB and EJB Bean-Managed Transactions

Tomcat, out-of-the-box, does not include a transaction manager implementation that supports the JTA APIs. You can choose among several approaches to migrating application code that uses JTA, whether through POJO services or EJBs using bean-managed transactions:

  • The most direct migration approach, often requiring no code level refactoring, is to plug in an external JTA transaction manager (such as Atomikos). Because a third-party JTA transaction manager is an additional component that must be obtained, supported, and possibly licensed, examine the desirability of this approach against the alternative of refactoring code away from the use of JTA.
  • Eliminate JTA API usage by refactoring code to use corresponding local resource transaction APIs. This would include, for example, direct driving of transactions through the JDBC Connection object, JPA's EntityManager, Hibernate's Session, or equivalent. Application code that uses local resource APIs should essentially run as-is in a Tomcat environment.
  • Refactor to use the Spring Framework transaction management functionality and abstractions. With this approach, code is decoupled from the exact transaction management strategy, and works equally well with JTA and local DataSource transactions. It also provides integration with lower- level, data-access support infrastructure. Many large IT organizations using JEE Application Servers have already standardized on Spring, making the code both much more portable and more maintainable.
  • When moving code that drives transactions programmatically, refactor according to Spring's programmatic TransactionTemplate.
  • Alternatively, consider refactoring to the use of Spring's declarative transaction support. In this variant, transactions are demarcated via external (to the code) XML-based declarations, or internal annotations right in the source. While moving to this declarative approach will require additional work, transaction handling boilerplate will be removed from application code, with the general net benefits of significantly simplifying and clarifying application logic, reducing the amount of code that must be maintained, and reducing the chance of bugs.

Session EJB Migration Strategy

EJB 2.x session beans are not available in a Tomcat environment. A migration to Tomcat entails refactoring any application logic currently implemented as session beans. EJB 2.x session beans are generally considered dead-end, legacy technology (if indeed they were ever a good idea), which is another factor that drives refactoring of this code.

The general approach to refactoring session beans is to re-implement the logic as POJO services. General concerns stem from handling transactions for the session beans, and to a lesser degree, the handling of security.

Session Beans with Container-Managed Transactions (CMT)

CMT implies that transactions are applied to EJB code through a declarative process, where the EJB deployment descriptors are annotated to indicate that the container should make certain methods transactional when invoked. The use of CMT must be refactored by one of several approaches:

  • You can implement transactions programmatically (similar to bean- managed transactions), where application code explicitly drives transactions. Spring's programmatic TransactionTemplate is a good choice, as you can decouple application code from the specific JTA or local DataSource transaction APIs. Additionally, Spring provides integration with lower-level data access support functionality. Otherwise, application level code may drive transactions by using the specific transaction API available. This includes JTA where an external JTA transaction manager has been plugged into the Tomcat environment, or a local resource transaction API that drives transactions directly through the JDBC Connection object, JPA's EntityManager, Hibernate's Session, or equivalent.
  • Alternatively, where Spring Framework is an available option, the preferred approach is to refactor to use Spring's declarative transaction functionality, as there is essentially a one-to-one mapping to the semantics of applying transaction demarcation. Spring's transaction support is a complete functional superset of that available in an EJB container. It can drive transactions through both JTA and local resource APIs, and contains additional integration with Spring's data access support code. Spring supports declarative demarcation of transactions through either external (to the code) XML-based declarations, or internal annotations right in the source.

Session Beans with Bean Managed Transactions (BMT)

See JTA: Non-EJB and EJB Bean-Managed Transactions, as the same general approach applies to migrating BMT code to Tomcat as POJO code, whether using JTA or local resource APIs.

Session Beans with Container-Managed Security

I’ve rarely found a client who used container managed security, due to it’s inherent limitations. You can annotate EJBs in a declarative fashion in their XML descriptors to indicate that the container should apply simple (simplistic?) role-based security to certain EJB methods. You need to refactor container-managed security by one of these approaches:

  • The most direct approach is to refactor to the use of declarative security through Spring Security. Spring Security, an extensible security framework, generally offers a complete superset of capabilities offered by EJB container-managed security, while also offering a large number of other capabilities, and being extensible in a container-agnostic fashion.
  • Alternatively, you can replace container-managed security with custom application-specific code created during refactoring, or by the use of another security framework.
  • Alternatively, you can use any of the third party application security products that offer API interfaces, for example CA’s SiteMinder or Tivoli Access Manager. Many IT organizations already utilize such security systems because they integrate application security with organization identity management.

Message-Driven EJB Migration Strategy

EJB message-driven beans (MDBs) are also not available as a technology choice in a Tomcat environment. A migration to Tomcat entails some refactoring away from MDBs. However, because code inside MDBs does not have a significant dependency on the EJB container (as opposed to other types of EJBs), the preferred refactoring approach requires minimal (if any) code-level changes.

  • Refactoring requires the creation of additional application-level code to handle the looping and threading functionality around message reception. This functionality was previously handled by the EJB MDB container.
  • Another approach is to use Spring Framework's Message Driven POJO (MDP) functionality. MDBs are not inherently tied to the EJB container at the code level, because they are generally a class implementing the JMS MessageListener interface. Spring's MDP container functionality can also handle message-dispatching (including all needed internal threading and looping functionality) to MessageListeners. Refactoring to the use of Spring does not generally imply code level changes, but rather configuration of the Spring MDP container. Spring's MDP capabilities are a functional superset of EJB MDBs, but offer a number of additional capabilities, including the ability to drive messages to complete POJOs that do not even implement MessageListener and to allow the automatic conversion of a JMS message to other data types, when receiving or sending messages.

Entity EJB Migration Strategy

EJB 2.x entity beans are not available in a Tomcat environment. Migration to Tomcat requires refactoring of persistence logic currently implemented as entity beans. Entity beans are considered dead-end, legacy technology, and their use fell out of favor a number of years ago. Where legacy applications still use entity beans, their disadvantages are an excellent argument for refactoring, with or without a migration to Tomcat. Many IT organizations have standardized on third party Data Persistence solutions, including Hibernate and Kodo.

The goal in refactoring away from entity beans is to end up with an interface-based, decoupled data-access layer, so that to the extent possible, higher layers are mostly agnostic to actual persistence choices. Three of the technologies that exist for implementing persistence logic in the data access layer are:

  • Hybrid JDBC/ORM: The best example of this approach is iBatis, from Apache.org. iBatis essentially externalizes input/output and mapping logic to external files containing the SQL, while also offering some elements from object relational mappers, such as declarative mapping of data types, and automatic eager or lazy loading of related entities. iBatis does not perform change tracking in the nature of a true ORM. However, Spring Framework's iBatis support eliminates most resource management and try/catch boilerplate that would otherwise have to be used with iBatis.
  • ORM frameworks: ORM frameworks, such as Java Persistence API (JPA), Java Data Objects (JDO), or defacto-standards such as Hibernate, employ a higher-level, declarative approach to persistence, where the framework performs mapping between Java objects and the database, tracks changes to entities while in use, and handles related functions such as eager or lazy-loading of related entities. Some scenarios lending themselves to ORM use include:
  • Somewhat lower transaction volumes and/or more complex object graphs
  • No legacy schemas with use of DB features or relationships precluding use of ORM
  • Weaker SQL and/or DBA skills in-house
  • Limited or no use of stored procedures
  • JDBC: JDBC is a lower-level approach but is a strong choice in some scenarios. Consider the use of the Spring Framework's JDBC support, which eliminates most resource management and try/catch boilerplate typically associated with JDBC, while also offering low-overhead mechanisms to implement mapping logic. Some scenarios lending themselves to JDBC include:
  • Higher transaction volumes and/or simpler object graphs
  • Legacy schemas not amenable to object relational mapping (ORM)
  • Strong SQL and/or DBA skills in-house
  • Use of stored procedures

EJB Client Access Code Migration Strategy

Client code that accesses EJB functionality sometimes accesses EJBs through an abstraction or lookup layer, so that the client code is only aware of plain Java business interfaces. In general, this type of client code does not require significant refactoring when you are moving away from EJBs.

Where EJB client code has direct awareness of service EJBs, EJB stubs during lookup through JNDI, EJB exceptions, or EJB remote interfaces, you must refactor the client code as part of refactoring the service EJB code to plain Java service implementations. For migrations in which the Spring Framework is available and many EJBs exist, consider migrating EJB client code to use Spring's EJB proxies as an initial step. Client code working through Spring's EJB proxies is generally unaware of EJBs, and is concerned simply with business interfaces. The decoupling achieved in this fashion will then facilitate the Migrate in Pieces migration strategy, as it allows client code to be unaware of when exactly EJB service code is migrated.

Remoting Services

Existing application code that accesses or implements non-EJB remoting services through RMI can migrate essentially unchanged to a Tomcat environment. Convert remote EJB’s to POJO services as described in the preceding section on migrating EJB’s, and where remoting is still needed, implement remoting using RMI or another appropriate protocol.

Where remoting is desired, and some refactoring is needed regardless, consider using Spring's transparent remoting functionality. Spring Remoting allows POJO services to be exported in a declarative fashion, over a number of wire protocols, without the  services having to be aware of or coupled to the remoting protocol. Similarly, on the client, side, Spring can create client-side remoting proxies such that client code calling through the proxies is unaware that it is talking to anything other than a local business interface.

Data Sources

In a full stack application server environment, DataSources are typically application server-managed connection pools bound to the JNDI tree. When migrating to Tomcat, you can bind an instance of the high concurrency connection pool provided with Tomcat to Tomcat's JNDI tree, allowing client code to work as-is. Another common connection pool in usage in Tomcat environments is Commons database connection pool (DBCP), although the high concurrency pool is recommended for its higher scalability.

It is also quite common to embed the connection pool in the deployed application itself, where it is a product, such as DBCP, that allows this scenario. DBCP makes this process very easy, because you can create and configure it as a simple JavaBean.

Security

Existing code utilizing Servlet spec security in the web layer will normally work unchanged in a Tomcat environment. That said, it is fairly rare for any real world application to depend on the Servlet spec security model and all the major JEE server vendors have augmented JEE security by adding sophisticated user privilege management services to their servers, as well as offering stand alone security products compatible with their JEE servers.

It is slightly more common for applications based on WAS to utilize container-managed security for EJB’s, although even there it is more common to utilize IBM’s excellent Tivoli Access Manager security, CA’s SiteMinder, or any of a number of third party application security products. In the case of WLS, BEA incorporated a comprehensive user/application security service directly into the server, and also offers a commercial upgrade that manages security for other environments. CA, IBM, and Oracle/BEA work with Tomcat, and user security generally transfers fairly readily.

Messaging

The Tomcat environment does not provide an embedded message queue. As such, when moving applications from a full-stack application server environment where an embedded message queue in that environment is being used, an external message queuing product must be used alongside Tomcat. A number of options are available to you, both open source (for example, ActiveMQ) and commercial.

Convert EJB message-driven beans as described in Message-Driven EJB Migration Strategy. Where messaging-related code is being refactored, consider using Spring's extensive messaging functionality, to reduce messaging boilerplate in general, and to take advantage of Spring's out-of-the-box container managed Message Driven POJO capability.

Other messaging code should normally work unchanged in the Tomcat environment, once an external queue is plugged in, with the caveat that any vendor-specific code must be converted to the new message queuing product.

Administration and Management

Completely separate from the JEE specification (and other services) provided by the commercial JEE servers, these products also provide sophisticated management capabilities that are used by developers and IT administrators alike. Tomcat lacks most such capabilities, which makes the migration process somewhat more difficult for developers trying to debug the migrated code.

Many IT organizations have “rolled their own” Tomcat administration solutions. Some of these are excellent, but also have represented a major investment. They also tend to be script/console based and have fairly steep learning curves. None of the solutions I’ve seen include monitoring or management of other environments or of the complete stack, much less things like virtualized instances.

A number of commercial offerings are available that include a managed version of Tomcat environments, including VMware/SpringSource tcServer and MuleSoft’s Tcat Server. VMware/SpringSource’s product includes a Hyperic subset and is upgradable to full Hyperic for those environments where sophisticated monitoring and management is needed up/down the stack and across multiple environments. MuleSoft’s product is based on LambdaProbe, and while it is much less functional than Hyperic, it has also been optimized for Tomcat monitoring and management.

Conclusion

We’ve been discussing the conversion of applications from JEE Application Server’s to Tomcat based deployment environments. We’ve reached a number of conclusions, based on both IT industry experience and on expert advice. Some of the most important points are:

  • IT organizations can achieve significant benefits, both in total cost of ownership and in reduced weight/complexity, by migrating applications from JEE Application Servers to Tomcat.
  • It is extremely important to plan such migrations and to create organizational agreement for both objectives and costs.
  • Not all applications hosted on JEE Application Server are suited to migration…in some cases eliminating all the dependencies on JEE Application Server functionality is simply too costly.
  • Typically, Tomcat add-ins/plug-ins will be required for common application services that are beyond the scope of the Tomcat project charter. Remember that while Tomcat is demonstrably an “application server”, it is NOT (and not intended to be) a JEE Application Server. This means that some services (messaging, data persistence, security, etc) will need to be layered around Tomcat.
  • Where migrating applications from JEE Application Servers to Tomcat is both feasible and cost effective, IT organizations have multiple choices for both technology acquisition and support. These range from complete Open Source/DIY to using commercialized versions of Tomcat with support subscriptions. In all cases, with careful planning the IT organization can save significantly…sometimes in the millions of dollars annually, but using Tomcat is NOT free!

Take a hard look at where you are spending your IT dollars. You can save a lot by telling your JEE Application Server vendor “thanks, but we’re moving to Tomcat!"

Andy has recently decided to make the jump from individual consulting to join the Spring Source team. He will continue to be working with major clients to assist them with IT architecture evolution, now as a member of a large and growing organization. His first project will be leveraging Tomcat, Spring, and a Tomcat based data grid/cache called GemFire. He’s looking forward to sharing the lessons learned with the tomcatexpert community. Andy has been architecting, designing, and building enterprise infrastructure and applications software for most of his career. He’s been responsible for BEA’s “Blended Source” initiative, combining the best of Open Source (including both Tomcat and Spring) with WebLogic, BEA’s WebLogic Enterprise Security product family, MEI Software’s financial systems, Netegrity’s SiteMinder security product, Camex’s electronic publishing systems, mainframe applications for Bell Telephone, and many others. During that time his hands on technology experience has ranged from octal coding into neon lighted switches all the way through JAVA and beyond, including many generations of “the best and final thing we will ever need”, and he looks forward to working on the even better things coming in the future. He was involved in the early days of Open Source software as a contributor to EMACS and refocused on Open Source during his tenure as Director of Product Management with BEA Systems, combined with a fascination for the rapidly evolving application deployment architectures and technologies driving today’s development. Andy has provided architecture and technology guidance for both vendors and IT organizations and he shares what he is learning through consulting services and through his web site, Enterprise Software Trends (www.estrends.com).

Comments

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.