Java write Code that is just run at compile time? - java

is it possible to write a "maven plugin" or something like that which changes the .java at compile time?
For example:
#Entity
... class ... {
#Id
long id
}
I would like to comment out all the Annotations and Create a ORM-Mapping.xml / Persistence according to the entitys

The annotations are mostly based on the configuration files which enable/disable their recognition.
Use the Spring profiles to distinguish the configuration classes. If the special profile will appear, no configuration classes will be recognized. The solution requires to make all the configurations configurable according to the Spring profiles.
#Configuration
#Profile("noAnnotations")
public class SomeConfigurationClass

It's possible. Project lombok modifies compiled code however there's no exposed API to do that. (See How does lombok work?) Which is what you want if you have to strip annotations. Disabling all annotations at runtime is probably not reasonable. If you just want to generate something from annotations found in compiled classes that is much simpler

What you describe sounds like you're looking for something like a C/C++ preprocessor/templating - feature?
Maybe Annotation Processing can help you https://docs.oracle.com/javase/8/docs/api/javax/annotation/processing/Processor.html
Apart from that - inferring a persistence.xml from your entities annotations is something the Spring Framework does.

Related

How to suppress warning 'cannot resolve method' because you generate the method using annotation?

My goal is to learn on how to create annotation. So, I use the project lombok's #Getter annotation for practice. However, one thing bothers me is that the IntelliJ IDEA throws warning of Cannot resolve method 'getId' in 'Product'. Please note, compiling is not a problem.
What I did:
Enable annotation processing in the Settings.
My expected result: The IDE knows that getId method will be injected at compile-time.
My actual result: The IDE throws warning.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
Product product = new Product();
logger.debug(Integer.toString(product.getId()));
}
}
import lombok.Getter;
public class Product {
#Getter
private int id = 10;
}
PS: I heard it needs Lombok plugin to be installed. Is there a way to do it without plugin? I need it to implement it in my own annotation.
Lombok isn't an annotation processor. Lombok is a unique bit of software, and (as one of the core authors), what lombok does is not trivial in the slightest: You'd have to fork the lombok code base if you want to do lombok-esque things.
Looking at lombok as an example of what annotations can do is in that sense not a good idea: Lombok is its own thing, and merely uses annotations to know where to act, it is not a processor (but, weirdly enough, it registers itself as one in order to become part of the compilation process).
To answer your direct questions:
Yes, you need the lombok plugin installed; recent versions of intellij have it installed by default if memory serves.
No, lombok cannot be made to work without that.
However, an actual normal annotation processor would work just fine.
Basic (non-lombok) annotation processors can only make new files - they cannot change existing files. Only lombok can do that (and it requires a plugin). If you write a basic annotation processor (which therefore can only make new files), what you've done (turn on 'annotation processing') is all that is needed.
Note that basic annotation processors tend to need to go through a full build and have issues with incremental compilation (as in, incrementally compiling tools generally just compile everything, every time, if annotation processors are loaded. Most tools know lombok isn't an annotation processor / works just fine in incremental compilation scenarios and know not to fall back to 'compile all the things all the time'). For medium to large project, 'compile everything' is a gigantic time waster which you want to avoid.
Next steps for you:
Consider if the changes you want to make can be done solely by making new files. If the answer is No, I must change existing files, give up. Or, fork lombok and spend half a year figuring out the inner workings of javac, ecj, and intellij :/
If you CAN do the job by making only new files, know that the experience won't be as smooth and speedy as what lombok does. Forget lombok as an example, it's not a normal annotation processor. Find any tutorial on annotation processing / read up on the APIs / have a look at the source of a project such as AutoValue for an example of how a 'normal' annotation processor works. Know that you can do what you want, and all it takes is what you already did: Enable that 'run processors' checkbox.
As noted in the #rzwitserloot answer,
do not use Lombok as a means to learn annotations.
Instead,
read an annotation tutorial.
Here are some links:
Oracle's Annotation Tutorial
Wikipedia's Annotation Page
Baeldung's Custom Annotation Article

What is use of Annotations in spring?

I'm a beginner to spring. All i see in using spring is configuring dependencies in xml format and enhance the maintainability by not changing the class files .but when we use annotations and auto wiring we are again recompiling class files which raised this question in my mind. can some body please explain the exact use of spring and auto wiring.
Spring became famous for most of it's loosely coupling capability. Classes are not dependent each other when you write them but they get their dependencies at runtime. Before annotations it is what XML handled the labeling classes etc. With annotations we can simply label a class being an entity by adding #entity annotation. So auto wiring means what ever the method we used to couple the classes will be used to wire up the classes at runtime.

Adding programmatic annotations to a Java class

Usage example:
I want to put on class fields a custom annotation #MyContainer and then add automatically on all such fields relevant Hibernate annotations (depending on field type and properties).
In additional I need to add JAXB XmlType annotation to the class and base the type name on the class name.
I would want additionally to add annotations to fields based on thier types, etc.
All added annotations should be available at run time (So hibernate / JAXB can find them).
I'm aware of the following options:
Pre-processing class source (bad option)
Processing during compilation with javax.annotation.processing APIs
Post compilation manipulation with tools such as Java Assist
Manipulation during class loading with java.lang.instrument APIs
Doing it with AspectJ (not powerful enough)
My primary goals are:
Keep sync between class and source for debugging
Support working from both Maven and IDE (Eclipse / Intellij)
I'll appreciate if people who already done such things can recommend the best approach for such a task (and perhaps potential pitfalls).
Here is a code example for defining custom annotation. This #TesterInfo is applied on class level, store the tester details. This shows the different use of return types – enum, array and string.
package com.mkyong.test.core;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE) //on class level
public #interface TesterInfo {
public enum Priority {
LOW, MEDIUM, HIGH
}
Priority priority() default Priority.MEDIUM;
String[] tags() default "";
String createdBy() default "Mkyong";
String lastModified() default "03/01/2014";
}
I think pre-processing class sources should be your preferred way. This enables you to have your sources in sync with the compiled classes, which is good for debugging as you mentioned. But it is also good for version control, since you are able to check in those generated annotations. It is also a lot more difficult to track down problems in your tool, if it is run it during compilation. IDE support should also be no problem when running your code generation in the generate-sources phase.
Edit:
Quick searching yielded some infos about programmatic java source modification
using the eclipse jdt or some thing in netbeans. But this might be worth some more research or a question of its own.
I want to suggest another approach on that. As my first answer might involve coding an own tool, you could also try a much simpler solution. As I hope you are unit testing your classes, you could implement a base class for every unit test of such a class. In this base class there is a test method, which checks that every field annotated with #MyContainer also has the required hibernate annotations.
We basically did the same thing, not for annotations but for serializability of fields and ran quite well with that approach.
To have it work most transparent in IDE, command line build and at run-time, option 1 (using APT) and option 5 (using AspectJ) will give you best fit.
For option 1 you'll have to implement your own annotation processor that will inject additional annotations based on the presence of your own #MyContainer annotation. Here is an example of this approach used for something similar.
For option 5 you can simply use annotation declaration. Something like this:
declare #field : * ((#*..MyContainer *)).*(..) : #OtherAnnotation();
Spring's Roo tool is extensively using option 5 and I certainly can't say it is not powerful enough.
There are few alternatives as mentioned above and each have its upsides and downsides. That's why I don't think there a real "right" answer for the above question. My purpose was to get inputs from the community and from people who had done such things in the past and have experience. Personally I've chosen to use the Instrument API with Javassist. This way the classes are extended on run time (although the same tool can be used for post compile processing). The nice thing is that the agent can be loaded from inside the JVM which avoids handling all the command lines. It will be great to hear on other alternatives.
Thanks,
Avner

Spring Meta-Annotations

Does anybody know what Spring JAR (and where to find it!) contains the functionality for Spring's so-called "meta-annotations". As this article shows, these cool "new" (well, sorta) constructs allow code like this:
#Service
#Scope("request")
#Transactional(rollbackFor=Exception.class)
#Retention(RetentionPolicy.RUNTIME)
public #interface MyService {
}
#MyService
public class RewardsService {
…
}
Basically, I have a Swing app that does not currently use Spring. I have a sudden requirement change that would be made supremely-easier if I could use these annotations.
So I'm just looking for the smallest, minimally-invasive Spring JAR where this functionality can be found. If absolute-need-be, I can use the entire Spring JAR, but it would be a very heavy-handed solution. It would be nice if Spring released a smaller JAR with smaller-scope functionality.
I'm browswing Maven Repo and see spring-core which contains a package called:
org.springframework.core.annotation
But upon inspection of the API docs it doesn't seem to be what I need...
Ancillary question: is it even possible to use these meta-annotations as standalone constructs, or do I have to use them along with, say, Spring DI or AOP or other major parts of the Spring framework?
Thanks in advance!
The annotations you want will be with the jar it is related to. For instance, the annotation org.springframework.transaction.annotation.Transactional will be in the spring-transactions artifact.
Meta-annotations are not really different from regular annotations other than the fact that Spring now detects Annotations on annotations whereas it didn't before. Whether annotations "work" or not depends on what is looking for them (in this case something in the Spring context).
For further reading see Annotation-based container configuration in the Spring framework reference.
There is project on github which is trying to provide meta-annotation functionality.
https://github.com/dblevins/metatypes/

Best practices when using Spring 3 annotations

I'm looking for some best practices when using Spring 3 annotations.
I'm currently moving to Spring 3 and from what I've read so far I see a lot of accent placed on using annotations and moving away from XML configuration.
Actually what is recommended is a mix of both styles, with annotations covering things that won't change often or from one run to the next (e.g. a #Controller will remain like that for the life time of the application), while the things that change and must be configurable go into XML (e.g. a mail smtp address, endpoints for web services that your application talks to etc).
My question is what should go into annotations and to what extent?
At which point annotations make things harder instead of easier? Is the technology (Spring 3) fully adopted as to be able to make such statements or does it take some more time for people to gain experience with it and then reflect on the issue?
It is always difficult to get real advanced information.
The easy tutorial with "look on my blog, I copied the hello word tutorial from Spring Source website... Now you can put fancy annotations everywhere, it the solution of all of our problems including cancer and starvation." is not really usefull.
If you remember right spring core had several purposes, among them:
to be non intrusive
to change any
implementation/configuration of a
bean at any time
to give a centralized and controlled
place to put your configuration
Anotation fail for all theses needs:
They introduce coupling with spring
(you can use standard anotation only
but as soon as you have at least one
spring anotation this is no longer
true)
You need to modify source code and
recompile to change bean
implementation or configuration
Annotations are everywhere in your
code. It can be difficult to find
what bean will be really used just by
reading the code or XML configuration
file.
In fact we have shifted our focus:
We realized that we almost never
provide several implementations of
our services.
We realised that being dependant of
an API is not that bad.
We realized that we use spring not only
for real dependancy injection
anymore, but mainly to increase
productivity and reduce java code
verbosity.
So I would use anotations when it make sence. When it is purerly to remove boilerplate code, verbosity. I would take care of using the XML configuration file for thing that you want to make configurable, even if it is only to provide a stub implementation of the service in unit tests.
I use #Value for properties that are configured in external properties file via PropertyPlaceholderConfigurer, as kunal noted.
There is no strict line for when to use xml, but I use xml:
when the bean is not a class I control
when the object is related to the infrastructure or configuration rather than to the business logic.
when the class has some primitive properties that I would like configurable, but not necessarily via externalized configurations.
In response to your comment: spring is very widely adopted, but "good" and "bad" are very subjective. Even my lines are not universal truths. XML, annotations and programmatic configuration all exists for a purpose, and each developer / company have their preferences.
As I said - there is no strict line, and no universal good practice for annotations.
Annotations are surely the way by which "newer" programming in java will continue. I use annotations for various uses...like #Scope for scope of bean, #Required for making dependency necessary, #Aspect for configuring advices,#Autowired for constructor injection using annotations. Since spring 2.5, annotation support has been good.
See here for spring tutorial, where annotation based issue are covered here.
I think that two cases that the usage of annotations could cause some problems. Firstly, if you want to write complex named queries (JPA) in your entities. I saw some entity code samples and asked myself whether the code is really java code or not. To many metadata in program code will reduce the readability of it which kills clean code principles.
Second problem is portability between JVM versions. Annotation is a feature 1.5+. If your software should support earlier JVM versions, then you may not use these.
Anyway, you can enjoy with annotations everytime without having any doubt and spare your time not changing IDE tabs to check XMLs if the property is still there or not, or entered correct etc.
For very small projects you could still XML version if you haven't too many stuff to be declared in spring. But, if you are in a huge project, the things could be very troublesome if you had 10 xml configs.
This will perhaps not help you much but at work they don't want to use autowiring because it needs a classpath scan (but that can be package-defined i think). So it increases the startup time of the application according to the size of the project.

Categories