In Project Annotation Proccessor
very short: Some classes are required by my annotation proccessor which when run first compiles the whole project to run which fails because of the classes that its generating missing in some other classes because they are loaded at the same time causing a chikcen egg problem. Running in different sub projects causes either a dependency loop or missing dependencies for some classes with dependencies.
full explenation:
I recently stumbled across annotation Proccessing and wrote one that works for my purposes as long as its in a different gradle project. However If I want to add something that utilises Classes from my main Code I need to change the location to that other class including that classes dependencies which is quite annoying. However I cant put it in the same project since parts of my code are generated using that annotation Proccessor. That means that the compilation which is needed before the processing fails since the imports to those auto generated classes fail since they are deleted on regeneration. meaning a chicken and egg problem. However the classes that use that generated code are not required by my processor. Meaning I basically would have to only compile the annotation processor first and then the classes as it needs them. After that the rest can be compiled. Question is how could I do that? any other way is also fine by me.
167 Replies
⌛
This post has been reserved for your question.
Hey @Hype_the_Time! Please useTIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here./close
or theClose Post
button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically marked as dormant after 300 minutes of inactivity.
Split it into two modules
you create one module containing the annotation processor
and one module with the actual code using the annotation processor
then the annotation processor doesn't run on itself
problem is that i need some of the classes and i get a dependency loop if i implement import them in gradle. for some classes i can use a simple string refernce but for some i actually need to check the class. mainly to check whther a class extends a other one.
Just only put the annotation processor code in the annotation processor module and make sure nothing in there needs the annotation processor
and that the annotation processor doesn't need the other module
annotation processors should ideally not run application code
my code doesnt run it but it uses it for some generation logic. mainly it checks for fields of the annotated class and whether they extend a specific class. there are some reasons for checking the class rn. not aware for a fix of that (without class being defined)
the annotation processor doesn't need to be dependent on these classes
you can implement it without the class being present
how?
Why would you need it for compiling the annotation processor?
the annotation processor can just use javax.processing APIs for accessing all the information it needs about application classes
i dont need it to compile the proccessor. i need it for logic that is generated by the proccessor
then what's the problem there?
Do you want to process generated classes? You can do that
it would just happen in a later round
mainly was missing a way to access the classes. (right now) i was using
com. squareup. javapoet
and i got a type nullpointer due to it being unable to reference the class type due too it not being accessible for it. one sec i am changing it to be in a different project again and coppying the exact erroryeah I think you can only access generated classes in consecutive rounds
how do consecutive rounds work?
javac performs multiple rounds of compilation. In each round, it calls
process
giving you information about what happened in the current round etcbasically i need to wait until a certain level and skip till then?
What do you need JDA's
Button
import for?
what are you waiting for?
if one generated class depends on another, you need to make sure you are generating the required class in the same round or before
What in there needs another class?i made a own button class and i generate some code based on it for conevniency. I was reworking it because my handler had like 2k lines. a bit long.
so what's the problem with generating code based on your button class?
Does your custom button class need the annotation processor for anything?
abstract button option assignable
Is that what's failing?
Hi, if you have some code used in a production code and also in annotations processor, you can extract it to a separated module...
not 100% sure since i dont have line of error in my stacktrace cause i am not able to debug it etc but i am pretty sure that it is this. happened after i added it.
recursive dependencies (code in it requiring dependecy which then requires a different class....) gets pretty annoying but yes. daniels rounds seems very promising so far from what i cought up which is saying nothing tbh.
From the Javadoc:
To be robust when running in different tool implementations, an annotation processor should have the following properties: The result of processing a given input is not a function of the presence or absence of other inputs (orthogonality). Processing the same input produces the same output (consistency). Processing input A followed by processing input B is equivalent to processing B then A (commutativity) Processing an input does not rely on the presence of the output of other annotation processors (independence)https://docs.oracle.com/en/java/javase/21/docs/api/java.compiler/javax/annotation/processing/Processor.html
Processor (Java SE 21 & JDK 21)
declaration: module: java.compiler, package: javax.annotation.processing, interface: Processor
When does it crash? Why can't you debug it?
Does the annotation processor/compilation crash or does running the application crash?
you might want to follow that since not doing so may be annoying/cause unexpected things to happen
and if you need some things to be processed before others, you could also ensure that they are in different modules with the one that should be processed later being dependent on the one that should be processed earlier
If you want to debug the annotation processor itself, that should be possible
in Maven, you can just run
mvnDebug
instead of mvn
and attach a debugger
it probably works similar with Gradlei tried bootjar (due too spring) with debug in intelij but it never hit a breakpoiint even at the start of process etc
you need to attach a debugger to the compilation
in Maven, you'd need to run
mvnDebug
Stack Overflow
how do you debug java annotation processors using intellij?
How do you debug java annotation processors using intellij?
Preferably using IDEA IntelliJ. I tried setting a breakpoint inside the processor and running but it did not break.
this answer is for Gradle: https://stackoverflow.com/a/42488641/10871900
Stack Overflow
how do you debug java annotation processors using intellij?
How do you debug java annotation processors using intellij?
Preferably using IDEA IntelliJ. I tried setting a breakpoint inside the processor and running but it did not break.
and also others
got debugging to work.
Cannot invoke "javax.lang.model.element.TypeElement.asType()" because the return value of "javax.lang.model.util.Elements.getTypeElement(java.lang.CharSequence)" is null
fails when i continue after toList()
seems like
de.hype.bbsentials.server.discord.options.AbstractButtonOption
is not available
Is that class generated?hm package seemed to be wrong probably happened during a refecactor
well that explains it lol
while compilation didnt work again i expect these errors that i see right now. those are from other places which i still need to fix. some due too outcommented stuff. maybe there is one hiding some where in those error but for now seems to be done
tyvm @dan1st | Daniel
ok
if you have more questions about annotation processors, you can continue asking here or create a new post and ping me (you can ping me for other annotation processing related questions, please not necessarily for other questions)
yeah was ware.
i would close it but i want to keep it open until ik its done. if i remeber by then ill close it
if you don't, it isn't much of an issue
very much aware
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.
@dan1st | Daniel Sorry for the german error message but thats what the compiler gives out to me. otherwise would have used english. normally i know what the problem is due too the stacktrace but I didnt find any code in it thats by me. I am also confused since my log is basically telling me its happeneing after me proccessing.
cutted log. last round:
Hinweis: Generating start
Hinweis: Generating done
Hinweis: Modal Processing start
Hinweis: Modal Processing done
I expect the button annotation porccessor to generate bad code rn. but commenting out the last change that is causing bad code isnt fixing this error seemingly. I tried gradle reload and clean.
I did find something which is causing a suspicion though:
thats linking between each other. its a first idea i will try to have a look at
looks like either something within the annotation processor overflows or it generates code for generated code from generated code etc
so you'd be stuck in an "infinite" loop of generating code until it overflows
can you tell whether this is deffenetley not it then?
Did you attach a debugger to the compilation process?
i attached ones at the try catches in both of the processors. they did not activate but were attached
Is there maybe generated code using it? Is EphemeralPolicy or IEphemeralPolicy using it?
Were you able to step through?
it paused if i set it withing the code
Is there any generated code using that class?
ok so it happens after all the process() calls, right?
in the log i provided there is some logging that for me looks like its after the proccessing of the annotation processors
full-log.txt
Can you verify that with the debugger?
You can use
roundEnv.processingOver()
dont know in which way you mean. will need it more specific for what to test
Does that return true in a round before the exception? Does process() finish before it?
ill try
the compiler calls process() any number of times. The last time,
processingOver()
should return true
like this?
yes
it hits
Is that printed?
it activates
My guess is that you are generating invalid code in some way
yeah I see
looks like something is referencing itself maybe
if you think it's that, maybe skip generating that class
if that resolves the issue, generate it but without any methods (assuming you are currently generating it with methods)
I dont know of how to descirbve it very well but simply all classes annoated in some way extend that class.
i will have to search for a solution to test for it.
Can you change it to
public class ...<Event, EphemeralPolicy>
without any bounds?
for testing?
but yeah idk whether generating a superclass is possible
interfaces might work thoughno they always extend that class. that class itself never gets generated. no class extends this one directley but they usually have another class in between
I dont think so since its more complicated. i have to find a actual soltuion bercause theres quite a lot of usages. working on it
that doesn't make it better
whatever you do: make sure there are absolutely no circles/circular dependencies at compile time
oh so this would be a issue that only comes if a annotation processor is used?
maybe
unlikely but possible
maybe you also have a case of something like A extends B extends A
which is never allowed
Do you have any generated class with more than 100 members?
would have been surprised too. when i was making it i was like oh intelij isnt sayin g no? strange. wouldnt expect that this is possible lets do it if its possible tho
100 members?
wdym
Do you have any generated method (including constructors and initializers) with more than 100 method calls (e.g.
a().b().c()
- this is known to cause StackOverflowErrors during compilation)
methods, fields, inner classes, etc
you can view the generated code somewhere in the build directoryI doubt it. I got a fix for the type refernce loop idea i had and now its throwing other errors but ones that I can work iwth.
also you can enable more detailed logging within javac - that should give you information on what type it was compiling that caused the issue
that may be useful in general when you get weird errors in javac
uhhhhhh
a) what argument
b) will take time to find in intelij because i doubt that its easily possible for me outside due too dependencies that are handled by gradle etc
a) if you get a weird error from javac, you can enable that logging for inside javac - I think that should tell you what javac is compiling and when
b) I think you can tell Gradle what to CLI options to pass to javac
Does your annotation processor run before or after the
Klasse ... wird geprüft
logs?
seems like the error occurs after compiling
you could try using a different compiler instead of javac - for example EJC
maybe that gives you a better error messageno clue on how to check.
also its ~ 11pm rn so I should probably cool down for today and go sleep and continue tomorrow.
I think Gradle can be configured to use EJC
if you want to try that
might not work well though - just for testing
and for it being 11pm: I'm in CEST as well
I mean we all know staying up till like 2 or 3 am but was programming a lot today so kinda exhausted as well.
Also gn.
xd
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.
will have a look now
you might be onto something there. but will need a clearer instruction on how to check.
that's not actually using EJC
what do i need to change?
you might need to tell gradle to fork the conpiler
Stack Overflow
Gradle: How to compile Java by eclipse ECJ (JDT core) by running Gr...
I have a project that can be build well by eclipse (ECJ) But Oracle javac can't build it (some reasons like in link: the different of ecj and javac).
I would like moving from eclipse to build by G...
Are you compiling Kotlin code?
if you want to use EJC, you'd need to do something like that I think
but it's fine if it doesn't work
i use gradle dsl aka kotlin gradle. uses other ways to reference stuff.
under that assumption I assume it can be converted to:
however
The configured executable does not exist (/home/spieler/.gradle/daemon/8.5/java)
hm, interesting
yeah idk that much about gradle
same
the executeable java is casuing the problem
i assume it would be fine if i just say nothing so it uses default aka whatever it needs?
you can maybe set
executable = "java"
to executable = "/usr/lib/jvm/YOUR_JDK/bin/java"
or similar
for testing
or don't do the tests with EJCwhat then?
you could create a copy of the project
and remove everything you don't need for reproducing the issue
(you can use git to save your state)
until you have a truly minimal reproducer
oh god.
2024-12-24T16:24:50.060+0100 [ERROR] [system.err] Unrecognized option : -Dfile.encoding=UTF-8
This message has been formatted automatically. You can disable this using
/preferences
.that's interesting
i mean lets say it this way i did find something
Did you remove the
executable = "java"
completely?wait how is this done?
yes
the bot detected that you posted some code
and used a codeblock
no but that its a app with same name and icon
it's a new message sent with a webhook
like webhooks have limits etc
how do you handle the limitations from discord side regarding count tho
What limits are you talking about specifically?
like max ones to exist or sth
it's only one per channel
you can set the name for every message
within the message
same for the profile picture
wait you can set those with webhooks?
yes
GitHub
JavaBot/src/main/java/net/discordjug/javabot/util/WebhookUtil.java ...
General utility bot for the Discord Java Community - Java-Discord/JavaBot
welp i will for sure have a look at that i was looking for something like that
Discord Developer Portal
Discord Developer Portal — API Docs for Bots and Developers
Integrate your service with Discord — whether it's a bot or a game or whatever your wildest imagination can come up with.
do you know whether jda has this supported?
we also do a bit of fun with it - for example if you post a message containing "fuck"
or will i need to use a library / self programm
test fuck
fuck
What?
lets try again
fuck
maybe that one doesn't like threads
nothing weird in the logs and also not overloaded - idk I'd need to check
this is what happens: https://canary.discord.com/channels/648956210850299986/653633234898255943/1321138299951251549
hugging test
ic
good to know will work on it
also back to topic
anyway when I create a minimal reproducer like that, you can do the following:
- Create a new local branch (or a copy of the project and
git init
)
- Make sure everything is committed
- Remove parts of the project where you think the issue would still occur (you can remove like half of the project at once)
- If the issue still occurs, commit
- If it doesn't, checkout/revert to the previous state
- repeat
that's what I typically do
I did that with bugs where it fails during a native-image compilation which takes like 30min to compile on a somewhat decently-sized projectbtw i was able to find something sus related already yestrday. maybe you missed me saying it.
due to git and it "only" being 2 commits i went back those 2 and it worked again. during that the type loop was noticied by me. when i went in and changed it to sth different which isnt as great but still decent i do not get that javacompiler error anymore
Do you know what exactly is the loop?
you could also create a new project with only the type loop and check whether you can reproduce it
<Event extends BBDiscordInteractionEvent<?, EphemeralPolicy>, EphemeralPolicy extends IEphemeralPolicy<Event>
event requires ephermeral but ephermeral requeires event
that compiles for me
could it help if we go into a vc or sth so i can screenshare?
wait will need to wait tho forgot about something
but option later. maybe in an hour or 2
does it work with a annotation processor?
didn't test it
might be important
yeah
hm is this important maybe?
public enum ActionEphemeralPolicy implements IEphemeralPolicy<BBDiscordInteractionEvent<?, ?>> {
public interface IEphemeralPolicy<Event extends BBDiscordInteractionEvent<?, ?>> {
might be important of how they work togeter
basically my goal was to say hey this event will use yourself as this type
Can you show the signature of an implementation?
wdym
Something extending the generated class
check your dms
i don't even have any JetBrains IDE installed
ok
I can try reproducing it later with an annotation processor
i dont knwo of how to describe it very well
its a complex construct i would say
but it may be useful to have one of the classes extending the generated abstract class
This message has been formatted automatically. You can disable this using
/preferences
.+ public interface IEphemeralPolicy<Event extends BBDiscordInteractionEvent<?, ?>> {
What exactly is the signature of
BBDiscordInteractionEvent
?public abstract class BBDiscordInteractionEvent<T extends GenericInteractionCreateEvent & IReplyCallback, EphemeralPolicy> extends GenericInteractionCreateEvent implements IReplyCallback {
the events etc come from discord jda
for reproducing later
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.
bot, this is active - I'm testing
how did THAT happen
I reopened the post without sending a message
and there was no message within 300min
i sent messages in here previously tho and insta deleted and it stayed open for a while at least
yeah I didn't
strange. whatever
anyways that compiles without an annotation processor
but note the comment here:
I took that code from you
it doesn't even care about deleted messages
it checks every 10min and if there are no recent messages, it marks it as "dormant"
i am not an expert but my goal was to tell it you can exoect this event. but one of my classes also needs to know which ephermeral policy to use so i needed to tell it that, but the epeehermreal policy also needs to know that it can expct itself for equal and which event it can expect which is kinda cusing a loop if done like it. instance of can work as a replacement but i dont like it as much
Does it expect an
IEphemeralPolicy<BBDiscordInteractionEvent<?, ?>>
but does not allow IEphemeralPolicy<SomeSubclassOfBBDiscordInteractionEvent<?, ?>>
?
IEphemeralPolicy<BBDiscordInteractionEvent<?, ?>>
means that the type parameter must be exactly BBDiscordInteractionEvent
- not any subclass and not any superclasswdym
Stack Overflow
Is List a subclass of List? Why are Java generics not implicitly po...
I'm a bit confused about how Java generics handle inheritance / polymorphism.
Assume the following hierarchy -
Animal (Parent)
Dog - Cat (Children)
So suppose I have a method doSomething(List<
hm
might be important
yeah - I'm telling you because I noticed that there
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.
Alternatively you could try the following:
- The compilation that fails still generates the source files from the annotation processor.
- You can try running
javac
with -proc:none
(no annotation processor) and compile both the sources and the generated sources together
I was able to compile that using an annotation processor generating the marked parts without issuesso I guess it's something else
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.
i found a easy work around that is way simpler. it called:
Simply use a abstract method that returns a boolean and let the super class define the rest. when you then use a extend class architecture you define it once and it works everywhere else anyway.
worked on sth else for a bit but are resuming now on this part.
anyway ty for your time. was very much appreciated.
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.