(English) Java EE Annotations – the Gap

Desculpe, este conteúdo só está disponível em Inglês Americano. For the sake of viewer convenience, the content is shown below in the alternative language. You may click the link to switch the active language.

Annotations are some sort of metadata type. They can be applied on type definitions, variables, methods, parameters, fields, annotations themselves and in more places with Java 8.The point of having this metadata is to be able to process it and have some routines executed inputing such meta-data. Annotations can be processed in compilation and runtime, but not all annotations make it to the runtime nor the compile time. The availability of an annotation in compilation and or runtime depends on the retention policy applied to it. The annotations processed during compilation usually change source code files and generate new source files that get compiled immediately. Some compilation time annotations are used to check code correctness, for example the @override annotation forces the compiler to consider that a specific method is overriding some parent’s method, throwing an compile error if not a legal override.To process an annotation during compilation is necessary to create an annotations processor (compiler extension) and register it according to Java services API specification.What happened before the introduction of annotations on JAVA EE APIS was that we had to configure most of the APIS in XML files, for example, Mapping a Servlet.All the Servlet Container had to do was: read and parse the web.xml file, then, validate the file and then apply the configurations if no validation error could be found. This was possible without having to add a single 3rd party library, using the Java XML API. We couldn’t deploy a Servlet without having to create the deployment descriptor. Well, not anymore.Annotations added a second way of getting a servlet up and running. It can be done without the web.xml deployment descriptor and it obviously comes with an associated cost.I created an annotation with the appropriate retention policy to make it available in runtime. Created a Servlet context listener so that I could detect the servlet context readiness and then find all type definitions that were carrying my annotation. By all type declarations, I mean, all classes and interfaces.Where are the type definitions stored? They all live under the WEB-INF directory. Some under the classes sub directory, others under the lib sub directory. But wait? The lib directory holds jar files. Wait! Am I going through each jar file and each file under the classes directory? Yah, I don’t have another option. If we want to detect all type definition carrying one annotation, we have to search everywhere. This is the first evidence of the overhead.The deployment is getting slower guys. Okay. Let’s just say we will iterate over the files on that directories. What to do with each of them? It depends. If it is a jar, we have to unpack it (in-memory operation) so that we can get to the class files. What do we do with the class files? We have to see if they contain the desired annotation, which means we have to load them, right? No. It would be a terrible mistake. Loading a class can only be done from a class loader. We would have to create a class loader instance and force it load all classes immediately while it uses lazy loading by default. More than creating a class loader and forcing it to load all the code, we would be running other serious risks. Imagine if there classes that have static blocks of code. Such blocks will be executed once we load such classes. Loading the classes is a bad idea. What now? We have to read the bytecode and find the annotations there. Seriously? Yah. We don’t want to spend a year learning about the JVM specification, do we? No, that’s why we will use a library that can read the byte code for us. Javaassist (https://mvnrepository.com/artifact/org.javassist/javassist) is the most famous. Using this library we can read each class file and detect the annotation if present. But there is a price to paid here: the javaassist has its own dependencies (more jar files) and such dependencies will also be scanned. The deploy takes longer and longer and honestly we don’t want to deal with bytecode even through a comfortable library. We want to find annotations. For that purpose, many frameworks out there are using Jandex (https://mvnrepository.com/artifact/org.jboss/jandex). It basically indexes meta-data about classes in your project (classes and lib directories) in order to make the lookup process painless and less time consuming although the index task still a time consuming activity.Jandex needs at least the file path of a .class file or a .jar file in order to index its meta-data. How are u going to deal with global libraries, the libraries that are not under your WEB-INF directory? How are you going to be able to find their real path without having to scan the entire global libraries directory and without having to dig on every JAVA EE server internals? This is the dark-side of the so loved annotations. I have to say, they make our life easier in one perspective (using) and other in the other one (processing).The XML files deployment descriptors are boring but honestly they deploy faster and have less complications. Maybe there is going to be a painless and soft way of scanning annotations after compilation one day.

Receba nossas actualizações por email

Ver Campanhas anteriores.

(Visited 32 times, 1 visits today)