Estimated Design Principles for Jakarta EE
- Transfer
Hi, Habr! We recently published the book " Learning Java EE. Modern Programming for Large Enterprises " from the German Java-champion Sebastian Dashner.
Mr. Dashner actively writes and speaks on topics related to modern Java EE, so his blog also paid attention to the general design principles for the Jakarta EE platform, now being developed by Eclipse. Translation of this particular article (June), we offer today to your attention.
The Jakarta EE platform gradually comes into its own, and with it, new specifications for enterprise development appear. To harmonize the various standards and technologies that are about to take shape, the entire Java EE community will benefit if it is possible to work out general design principles for the Jakarta EE specifications.
I believe that Java EE technology has proven so successful thanks to just a few principles. Below, I present my point of view as to which design principles established in Java EE seem to me the most important, which are worthy of further elaboration and can potentially serve as recommendations for designing in Jakarta EE.
I decided to write this article, inspired by the proposals of Dmitry Kornilov on the direction in which the technical development of Jakarta EE should go.
First of all, the business logic of the
Java EE programming model allows the developer to focus precisely on what is required - that is, on the business logic. No longer need to inherit API classes; The developer can express the logic of his subject area in the usual Java language and mainly declaratively (using annotations) control the behavior of the application server. Thus, the framework is seamlessly integrated into your code and, in essence, it is just as easy to remove it from there. When designing, rely not on reuse, but on easy disposal.
However, implementations should relieve the developer from the most difficult work to the maximum - that is, allow him to distract from technical requirements not related to business logic. Examples are multithreading, transactions, inversion of control, or processing HTTP requests. On the application side, tediousness is a blessing :)
It seems to me important that the framework not only does not interfere with the implementation of business logic, but also stimulates programmers to more quickly develop development capabilities into production. There is no need to polish the framework to shine - it is better to bring the code of business logic to the ideal. Compare modern Java EE or Spring with old-fashioned versions of J2EE - I think you will immediately understand what I mean.
Jakarta EE should develop along the same lines and, accordingly, focus on specifications that allow developers to implement business logic as quickly as possible.
Configuration conventions
In Java EE, the configuration required to define a typical enterprise application is minimized. In most practical situations, agreements work right out of the box, no configuration is required. So, no more XML files are needed to configure a simple Java EE application. Another example is that JAX-RS provides default HTTP response codes corresponding to the return values of the JAX-RS methods.
Java EE does have enough flexibility to modify behavior and implement more complex scenarios; however, there is no agreement on this.
Jakarta EE should continue to turn the simple into the easy, and the complicated into the possible.
Interoperability of specifications
Jakarta EE should continue and extend the interoperability of specifications. In Java EE, the existing specifications and the functionality present in them, which has already become part of the standard, are followed.
Developers can rely on the fact that the disparate specifications will work well with each other, and no configuration is required. Standards were required: if the runtime environment supports both specification A and specification B, then A + B should interact with each other. Examples: component validation, JAXB or JSON-B can be used in the JAX-RS resource classes, and no further configuration is required.
Dependency Injection and CDI
Of course, it’s not desirable that things already exist in Jakarta EE be reinvented - for example, dependency injection related to CDI. It is desirable that the specifications use and highlight the strengths of the JSR 330 or, if necessary, CDI.
Fresh example - use
Another specific measure is as follows: specifications should provide CDI providers, and if necessary, typesafe qualifiers for the types that need to be created. So, at present, an instance of the JAX-RS client can only be obtained programmatically through the API
Declarative Approaches
With all this, the Java EE API relies heavily on a declarative approach, using control inversion. Thus, developers do not call the functionality directly; the container is responsible for calling the functional, and we rely on the code definitions. Examples (of the most advanced specifications) are JAX-RS, JSON-B or CDI.
Jakarta EE not only provides more comprehensive software APIs, but should further promote the use of declarative definitions and control inversion.
Deployment strategies
The most characteristic feature (and in my opinion, a great advantage) of Java EE is that the deployment model proposed here, in which business logic problems are separated from implementation. The developer programs exclusively for an API that is not part of the deployment artifact and is implemented by the application container.
Such compact deployment artifacts simplify and speed up program delivery, including build, publish, and deployment as such. They are also compatible with the levels of the container file system used, for example, in Docker. During the assembly process, you only need to rebuild or re-submit the changed elements.
Ideally, deployment artifacts should contain only business logic and nothing else; runtime implementations and potentially added third-party libraries are delivered at a lower level, for example, in application server libraries added in the previous container assembly step.
In Jakarta EE, expanded artifacts must also be considered first-class entities. Perhaps there will be an opportunity to further tighten the execution time environment based on the specification required by the application. However, in Jakarta EE it is supposed to pay maximum attention to the business logic and developer productivity, and the fine-tuning of the execution time is already secondary.
Testability
Applying the above principles, especially preferring declarative programming and dependency injection, we improve the testability of the business code. Thus, developers can directly instantiate objects in test scripts, since they no longer need to inherit the API classes or invoke the inconvenient functionality that they would previously need to simulate.
However, in Jakarta EE, it is required to seriously refine the standardization of integration testing at the code level, so that it does not depend on the manufacturer. Earlier it was with this that we had to deal with when working with Arquillian. In real projects, such a standard would be useful, which allows declaring only test deployment scenarios and invoking functionality for one or several components. Earlier, I wrote that I do not consider overly important integration testing at the code level, for example, when running an application in built-in containers. However, if you standardize integration tests at the code level, this clearly will have a positive effect.
Conclusion
I think it is no coincidence that Java EE APIs are so widely used in real projects: these APIs are well thought out and designed in accordance with clear principles, thanks to which it was possible to unify not even a single specification, but an entire platform. They allow you to use several specifications in one spirit at once. Here we managed to get rid of artificial obstacles that only complicate the work of the programmer - therefore, I think, all enterprise development has become much more pleasant.
Mr. Dashner actively writes and speaks on topics related to modern Java EE, so his blog also paid attention to the general design principles for the Jakarta EE platform, now being developed by Eclipse. Translation of this particular article (June), we offer today to your attention.
The Jakarta EE platform gradually comes into its own, and with it, new specifications for enterprise development appear. To harmonize the various standards and technologies that are about to take shape, the entire Java EE community will benefit if it is possible to work out general design principles for the Jakarta EE specifications.
I believe that Java EE technology has proven so successful thanks to just a few principles. Below, I present my point of view as to which design principles established in Java EE seem to me the most important, which are worthy of further elaboration and can potentially serve as recommendations for designing in Jakarta EE.
I decided to write this article, inspired by the proposals of Dmitry Kornilov on the direction in which the technical development of Jakarta EE should go.
First of all, the business logic of the
Java EE programming model allows the developer to focus precisely on what is required - that is, on the business logic. No longer need to inherit API classes; The developer can express the logic of his subject area in the usual Java language and mainly declaratively (using annotations) control the behavior of the application server. Thus, the framework is seamlessly integrated into your code and, in essence, it is just as easy to remove it from there. When designing, rely not on reuse, but on easy disposal.
However, implementations should relieve the developer from the most difficult work to the maximum - that is, allow him to distract from technical requirements not related to business logic. Examples are multithreading, transactions, inversion of control, or processing HTTP requests. On the application side, tediousness is a blessing :)
It seems to me important that the framework not only does not interfere with the implementation of business logic, but also stimulates programmers to more quickly develop development capabilities into production. There is no need to polish the framework to shine - it is better to bring the code of business logic to the ideal. Compare modern Java EE or Spring with old-fashioned versions of J2EE - I think you will immediately understand what I mean.
Jakarta EE should develop along the same lines and, accordingly, focus on specifications that allow developers to implement business logic as quickly as possible.
Configuration conventions
In Java EE, the configuration required to define a typical enterprise application is minimized. In most practical situations, agreements work right out of the box, no configuration is required. So, no more XML files are needed to configure a simple Java EE application. Another example is that JAX-RS provides default HTTP response codes corresponding to the return values of the JAX-RS methods.
Java EE does have enough flexibility to modify behavior and implement more complex scenarios; however, there is no agreement on this.
Jakarta EE should continue to turn the simple into the easy, and the complicated into the possible.
Interoperability of specifications
Jakarta EE should continue and extend the interoperability of specifications. In Java EE, the existing specifications and the functionality present in them, which has already become part of the standard, are followed.
Developers can rely on the fact that the disparate specifications will work well with each other, and no configuration is required. Standards were required: if the runtime environment supports both specification A and specification B, then A + B should interact with each other. Examples: component validation, JAXB or JSON-B can be used in the JAX-RS resource classes, and no further configuration is required.
Dependency Injection and CDI
Of course, it’s not desirable that things already exist in Jakarta EE be reinvented - for example, dependency injection related to CDI. It is desirable that the specifications use and highlight the strengths of the JSR 330 or, if necessary, CDI.
Fresh example - use
UriInfo
from JAX-RS in resource methods. The annotation @Inject
does not yet support the implementation of methods of this type. The more convenient it is for a programmer to work, the more he relies on a universal mechanism. Another specific measure is as follows: specifications should provide CDI providers, and if necessary, typesafe qualifiers for the types that need to be created. So, at present, an instance of the JAX-RS client can only be obtained programmatically through the API
ClientBuilder
. Manufacturers and qualifiers simplify the work of the programmer because they provide declarative definitions. Declarative Approaches
With all this, the Java EE API relies heavily on a declarative approach, using control inversion. Thus, developers do not call the functionality directly; the container is responsible for calling the functional, and we rely on the code definitions. Examples (of the most advanced specifications) are JAX-RS, JSON-B or CDI.
Jakarta EE not only provides more comprehensive software APIs, but should further promote the use of declarative definitions and control inversion.
Deployment strategies
The most characteristic feature (and in my opinion, a great advantage) of Java EE is that the deployment model proposed here, in which business logic problems are separated from implementation. The developer programs exclusively for an API that is not part of the deployment artifact and is implemented by the application container.
Such compact deployment artifacts simplify and speed up program delivery, including build, publish, and deployment as such. They are also compatible with the levels of the container file system used, for example, in Docker. During the assembly process, you only need to rebuild or re-submit the changed elements.
Ideally, deployment artifacts should contain only business logic and nothing else; runtime implementations and potentially added third-party libraries are delivered at a lower level, for example, in application server libraries added in the previous container assembly step.
In Jakarta EE, expanded artifacts must also be considered first-class entities. Perhaps there will be an opportunity to further tighten the execution time environment based on the specification required by the application. However, in Jakarta EE it is supposed to pay maximum attention to the business logic and developer productivity, and the fine-tuning of the execution time is already secondary.
Testability
Applying the above principles, especially preferring declarative programming and dependency injection, we improve the testability of the business code. Thus, developers can directly instantiate objects in test scripts, since they no longer need to inherit the API classes or invoke the inconvenient functionality that they would previously need to simulate.
However, in Jakarta EE, it is required to seriously refine the standardization of integration testing at the code level, so that it does not depend on the manufacturer. Earlier it was with this that we had to deal with when working with Arquillian. In real projects, such a standard would be useful, which allows declaring only test deployment scenarios and invoking functionality for one or several components. Earlier, I wrote that I do not consider overly important integration testing at the code level, for example, when running an application in built-in containers. However, if you standardize integration tests at the code level, this clearly will have a positive effect.
Conclusion
I think it is no coincidence that Java EE APIs are so widely used in real projects: these APIs are well thought out and designed in accordance with clear principles, thanks to which it was possible to unify not even a single specification, but an entire platform. They allow you to use several specifications in one spirit at once. Here we managed to get rid of artificial obstacles that only complicate the work of the programmer - therefore, I think, all enterprise development has become much more pleasant.