Java EE 7 in Production at Gam Electronics
One of the most important things to do at this stage of the life-cycle of Java EE is highlight successful adoption stories at a regular cadence. We have been doing just that for a long time through our adoption stories blog, the Aquarium blog as well as JavaOne. Ehsan Zaery Moghaddam from Gam Electronics recently reached out to us with a very nice detailed, well-written Java EE 7 adoption story. Another cool thing about Ehsan's adoption story is that it uses WebLogic. Yet another very interesting aspect of the story is that it is about everyday business technology in Iran. Many developers should be able to relate to the story - especially ones still making the transition from J2EE to Java EE. I asked him a series of questions on his Java EE 7 adoption over email; his answers are listed below. I have highlighted specific passages that really stand out.
Can you kindly introduce yourself?
I'm Ehsan Zaery Moghaddam and I'm the technical lead of the Java development team at Gam Electronics. My
professional career started at 2004 as a Java developer and throughout these years, besides developing some critical business use-cases, I was mainly in charge of evaluating and customizing open source projects to make them compatible with our architectural solution. Recently I was in charge of devising a new architecture based on Java EE 7 for the next generation of our products.
Can you describe the application or applications that use Java EE? What does your company do?
We are one of the most well-known office automation solution providers in Iran with about 600 clients, ranging from large banks and insurance companies to mobile carriers and municipalities. There are more than 300,000 users throughout the country working with our products on a daily basis. Our solution consists of an electronic correspondence system, a document archiving system and a workflow engine all developed using Java EE.
Why did you choose Java EE?
Java EE was a prominent candidate for us, both technically and strategically. From a technical point of view, having a wide array of APIs and services provided out of the box by application servers as well as being able to add different frameworks and libraries for any aspect of a software system when needed was a huge plus. Also strategically, being vendor neutral in different layers (OS, application server or even the JVM itself) let us to be more competitive by having more flexibility to cover client's requirements and reducing the TCO for clients. But in my opinion, one of the most important factors was that Java EE is an open standard and as can be expected, it is stable, backward compatible and comprehensive; hence making it successful and adaptable.
Most of our end users are using Windows and due to the smooth integration with .NET technology in the platform, we also have a small .NET development team that is mainly in charge of developing desktop components and applications required by some projects.
How does the application or applications use Java EE?
It?s a bit of a long story. We had two major migrations in recent years, one from J2EE 1.4 to Java EE 6 and next to Java EE 7.
We started developing enterprise applications in 2004 with JDK 1.4 and J2EE. We used to develop on
JDeveloper 9 while applications were being deployed on the Oracle Application Server. The development process was RUP and use-cases were the unit of work to be assigned to developers. So we needed to have developers skilled with the entire technology stack of the project to handle a typical task.
Our technology stack was a typical three-tier architecture comprised of JSP/JSTL/Struts 1 in the web layer, EJB 2 (with bean managed transactions) for service layer and Hibernate 2 for data access. Despite using the cutting-edge technologies and tools of that time, to cover their limitations and meet performance requirements, we had to develop some in-house components and tools. Obviously IDEs provided no support for such in-house components. As an example, features provided by Hibernate 2 to run a dynamic query did not cover our business requirements; hence we developed a dynamic query builder capable of handling complex queries and mapping results to POJOs. This is a feature nowadays provided by some open source tools like MyBatis.
As a result of incorporating such homemade tools, to develop a typical use-case, developers had to update multiple XML configurations or other non-java files which was a tedious and error prone process. This gradually increased development time and maintenance cost in such a way that the time it took to add a new feature rose significantly throughout the years and most of our clients preferred to stay at some stable release and refused to upgrade to newer versions.
To summarize, the major issues we encountered at this stage were:
- Reduction in development speed due to the high volume of LOC per use-case and large number of
configuration files (e.g. ejb-jar.xml, hbm files, custom query files, etc.).
- Improper use of some J2EE features (e.g. using BMT instead of CMT).
- Diminished motivation for developers to continue developing on a deprecated technology.
- Complex dependency graphs due to not using any standard build tools and relying solely on the IDE for the build.
- Lack of unit tests (or any automated tests at any level) to help refactoring code.
- Complex business logic that was implemented using if-then-else statements in code or external configuration
options instead of using a business process management tool or rule engine.
- Inability to update a huge number of intermingled JSP pages to make them cross-browser compatible and responsive.
- Using older software development processes and having an old-fashioned mindset regarding project
management and planning.
Having tens of thousands of active users spread across hundreds clients, the development team was spending most of it's time trying to fix issues or occasionally adding a small new feature, which had it's own risk of producing yet another issue. There was no time to stop, think and plan for a new solution. Furthermore most of the products were designed as huge monolithic blocks and it was almost impossible to redesign them partially.
In 2011 our company won a tender for developing the national citizen enrollment solution with smart ID cards. It
was a completely new project that could be developed from the ground up and a good opportunity to develop a
new architecture and evaluate the results. Therefore a dedicated team was assigned to the project and a new technology phase in our company began.
Due to the complexities involved in the enrollment process (e.g. connecting to different hardware devices to scan biometric data or taking a live picture from a camera) we decided to develop the client side as a desktop application using .NET. On the server side, we migrated to Java EE 6. We used JAX-WS instead of old-fashioned JAX-RPC that we had been using for SOAP web services before and this led us to smooth integration with .NET on the client side with minimum compatibility problems and without incorporating any third party framework like CXF or Axis.
In the service layer, we tried EJB 3.1 and developed our data access layer using JPA 2.0 and Hibernate 3. By using annotations to configure EJBs, throwing out RemoteHome and LocalHome interfaces, applying container managed transactions instead of manual begin/commit/rollback blocks and incorporating Interceptors to handle cross cutting concerns like audit log and permission controls, we got a huge reduction in total LOC and gained a great initial momentum.
By migrating our build process from an IDE based solution to Maven, we got rid of jar hell and
developers were free to use any IDE they liked. Most of them chose IntelliJ, but we had some Eclipse and
NetBeans guys too. Finally the project resulted in successful deployment to a single instance of WebLogic 12.1.2 capable of handling hundreds of thousands of requests using a single 32 bit server.
Shortly after starting this project, another small team was formed to develop a web based calendar system using a similar back-end architecture. The calendar was one of the candidate businesses that we were trying to redesign as a standalone application using newer technologies. Also for the first time we tried to design our user interface
as a single page application which led us to have a more user friendly UX.
Despite not utilizing all of the available APIs in Java EE 6 (e.g. CDI and JSF), in 2014 the development team had enough experience and confidence to start developing products using this new technology stack. Considering the productivity of the new team and their mindset about using an agile software development process like Scrum, managers decided to stop further development on the older platform and invest more on Java EE 6 or Java EE 7. By using new versions of WildFly and WebLogic capable of supporting Java EE 7, we decided not to repeat our mistakes again and started to upgrade our platform to Java EE 7 before trying to develop our next product.
Considering successful experiences in our last project with single page applications, we have decided to
use this paradigm for user interfaces across our product family. A UX sub-team has been formed and has started to
develop a responsive user interface based on Google Material Design and Sencha ExtJS.
On the server side, to have a more modular deployment model (maybe moving toward microservices in the future), we have tried to split up the system by identifying it's high level services and packaging them as separate war files. By doing so, we would be able to redesign and upgrade services more rapidly and independently. In the web layer we chose JAX-RS instead of Struts and all APIs were developed as stateless services. While developing a user story, we tried to finalize the UX first and then after discussing the required API with the back-end team, a draft version of APIs would be designed and documented using Swagger. Doing so minimizes the impact of the back-end and UX team on each other and we?re now able to serve a wide array of clients including our future mobile app or maybe a desktop version of some products.
By incorporating JAX-RS 2.0 filters, all incoming REST requests including their details (e.g. user agent,
request body and query parameters, resource address, etc.) are logged in dedicated log files that would be
processed and transferred by Logstash to an Elasticsearch server. Now we have a valuable monitoring
dashboard in Kibana which gives us a tremendous amount of information that was previously not achievable. We were never able to have such high quality reports due to ad-hoc AJAX requests that were developed in
different JSP pages each using a protocol designed by a developer for a specific use-case. By utilizing
JAX-RS filters, we have a unified protocol for request and response bodies in JSON. Furthermore using
JAX-RS exception mappers there was no need to use Interceptors to handle exceptions.
Another important change in the web layer was the extensive use of Bean Validation instead of validating input
parameters manually. Based on analysis of our old code base we noticed that a considerable amount of
code in a typical Struts action form was dedicated to validating input parameters. By using Bean Validation annotations and it's declarative syntax, JAX-RS resources are now more readable. The total LOC for the application has clearly decreased and the final output became more robust and testable .
In the business layer, we used EJB 3.2 to implement services in two levels: Service Facades (accessible by REST
endpoints) and actual Business Services. Besides cutting out some old J2EE patterns (like Service
Locator, Business Delegate and Value List Handler) we tried our best to utilize CDI capabilities as a glue to
hold all layers together. Using CDI, there was no need to use Factories or making JNDI look-ups to access
typical resources. Cross cutting concerns are now implemented using CDI Interceptors. In my opinion, CDI is the true magic of Java EE 6 and Java EE 7. It had a tremendous
effect on removing boilerplate code from projects and making them more readable, maintainable and
extendable; three core attributes that we were always trying to achieve throughout the years.
In the data access layer, we tried the Repository pattern using Apache DeltaSpike and JPA 2.1. By doing so, we
now have an array of interfaces in this layer and their implementations are automatically generated by DeltaSpike using method naming conventions. In case of more complicated queries, we use JPA?s NamedQuery and
NamedStoredProcedureQuery so we don?t use our homemade query builder component anymore. Additionally by incorporating the entity graph concept introduced in JPA 2.1, there is no need to be worried about
the old famous lazy initialization exception anymore.
Besides updating the architecture of our products, we also tried to utilize supporting products to improve the
overall development process and to keep the code quality at an optimum level over time. We tried to use code review tools like UpSource and also configured a CI pipeline using Jenkins to reduce the integration overhead we had before. This is one of the aspects that we?re still trying to learn to improve our productivity.
The company decided to redesign one of our old custom projects to evaluate the new architecture?s runtime performance and also measure development time. The project was a huge archive for the largest telecommunication operator in Iran that had been developed more than 4 years ago. The client had a bulk of feature requests and issues that the product?s development team had no idea how to handle in the old architecture.
To mitigate the risk of any data loss, we decided to keep the old database and design the new system on top of
it. While the initial estimate of redesigning the system by the old team was something around 5 month using a team of 2 developers (ten man-months), the initial version using Java EE 7 was developed in about 6 weeks using a team of just 1 back-end and 1 UX developer. The application is now ready to be installed on the client?s staging server so that they can give us some initial feedback regarding the new look and feel and performance of the system. The project was a huge success for my team and now we can proudly trust our new design as a basis to build the next generation of products for the company.
I think we can summarize the list of our achievements through these transitions as:
- Noticeable reduction in development time.
- Huge drop in the average LOC (something around a quarter for a typical use-case).
- Reaching a very testable design.
- Simplified troubleshooting and debugging due to reduced complexity.
- Boost in developer productivity by spending lesser amounts of time on boilerplate code and getting to concentrate more on the actual business.
- Reduction in maintenance cost due to having a more readable code base.
- Increased extensibility.
- Reaching higher levels of satisfaction for clients, end users and developers.
In my opinion, if we consider J2EE 1.4 as a LEGO set that has been presented to a boy to help him realize his imagination, Java EE 7 would be like a 3D printer that has been given to the same kid (who is now a young man) to make him free from the limitations of the old LEGO set and give him an opportunity to use his imagination to create new parts with higher resolution, assemble them and create innovative products.
How was your general experience with Java EE? Would you use it again?
Java EE evolved effectively during recent years. If you were asking me this question maybe round 2006 or 2007, I may had a different answer considering the introduction of Spring and DI concepts. But today the story has changed. By having two consecutive successful migrations in recent years and reaching such a high productivity level in our development team, I?m very satisfied for being part of Java EE and its surrounding ecosystem. I know that there are other platforms and technologies that may give me the same level of productivity or may beat it in some aspects, but as someone who has spent almost his entire career working with software development using this platform, I can say Java EE was the best choice for us and as is clear in
my previous answers, we?re going to use it in the next generation of our products.
However there is always something to improve in such a large platform. I think the security API provided in Java EE is one of the most important specifications that have not gotten updated in recent years and it?s not as handy as other parts of the spec. Also there are some other aspects of enterprise applications, like caching or NoSQL, which has not been covered by Java EE so far and this is where JCP could shine further.
How can people contact you if they have questions?
The best way is by email at zaerymoghaddam at gmail dot com or visiting my blog at developmentor.blogspot.com.
If you have a similarly great Java EE adoption story to share with the community (particularly migration stories from other technologies), please do feel encouraged to reach out. In the spirit of Java EE centric vendor neutrality, what Java EE implementation or tool set you choose does not matter at all and neither does which part of the globe you are in.