xmolecules / jmolecules-integrations

Technology integration for jMolecules
Apache License 2.0
79 stars 21 forks source link

Bytebuddy changes only work after a second package run #208

Closed DanieldeJongVeldstra closed 8 months ago

DanieldeJongVeldstra commented 8 months ago

To generate all spring annotations I am using the jmolecules-bytebuddy dependency together with the byte-buddy-maven-plugin which has the weird behavior that it only seems to work if I do a package where the target folder already exists from a previous run.

When I am running a mvn clean package command I notice the byte-buddy-plugin being executed, but when I am looking in my target directory I am noticing that the classes have not been decorated. When I do a mvn package again I notice that the decoration is done correctly.

Am I doing something wrong, is this expected behavior or is there a bug.

Output logs first run

[INFO] Resolved plugin: org.jmolecules.bytebuddy.JMoleculesPlugin
[INFO] Resolved entry point: REBASE
[INFO] Processing class files located in in: /Users/daniel/Dev/IdeaProjects/warehouse/management/target/classes
[INFO] jMolecules - Detected Jakarta Persistence…
[INFO] 
[INFO] □─ nl.daniel.dejong.inventorymanagement.application.product.ProductDefinitionService
[INFO] └─ Spring - Adding @o.s.s.Service.
[INFO] 
[INFO] □─ nl.daniel.dejong.inventorymanagement.application.product.ProductService
[INFO] └─ Spring - Adding @o.s.s.Service.
[INFO] 
[INFO] □─ nl.daniel.dejong.inventorymanagement.domain.product.Product
[INFO] ├─ JPA - Adding @j.p.Entity.
[INFO] ├─ JPA - Adding default constructor.
[INFO] ├─ JPA - Adding nullability verification using new callback methods.
[INFO] └─ JPA - Defaulting id mapping to @j.p.EmbeddedId().
[INFO] 
[INFO] □─ nl.daniel.dejong.inventorymanagement.domain.product.definition.ProductDefinition
[INFO] ├─ JPA - Adding @j.p.Entity.
[INFO] ├─ JPA - Adding default constructor.
[INFO] ├─ JPA - Adding nullability verification using new callback methods.
[INFO] └─ JPA - Defaulting id mapping to @j.p.EmbeddedId().
[INFO] 
[INFO] □─ nl.daniel.dejong.inventorymanagement.domain.product.definition.events.ProductDefinitionCreated
[INFO] ├─ JPA - Adding @EmbeddableInstantiator for record.
[INFO] └─ JPA - Adding @j.p.Embeddable.
[INFO] 
[INFO] □─ nl.daniel.dejong.inventorymanagement.domain.product.definition.valueobjects.ProductDefinitionId
[INFO] ├─ JPA - Adding @j.p.Embeddable.
[INFO] └─ JPA - Default constructor already present.
[INFO] 
[INFO] □─ nl.daniel.dejong.inventorymanagement.domain.product.events.ProductCreated
[INFO] ├─ JPA - Adding @EmbeddableInstantiator for record.
[INFO] └─ JPA - Adding @j.p.Embeddable.
[INFO] 
[INFO] □─ nl.daniel.dejong.inventorymanagement.domain.product.valueobjects.ProductBarcode
[INFO] ├─ JPA - Adding @j.p.Embeddable.
[INFO] └─ JPA - Adding default constructor.
[INFO] 
[INFO] □─ nl.daniel.dejong.inventorymanagement.domain.product.valueobjects.ProductId
[INFO] ├─ JPA - Adding @j.p.Embeddable.
[INFO] └─ JPA - Default constructor already present.
[INFO] 
[INFO] □─ nl.daniel.dejong.inventorymanagement.infrastructure.persistence.ProductDefinitionJpaPersistence
[INFO] ├─ Spring - Adding @o.s.s.Repository.
[INFO] └─ Spring Data - Not adding @o.j.d.a.Repository, already present.
[INFO] 
[INFO] □─ nl.daniel.dejong.inventorymanagement.infrastructure.persistence.ProductJpaPersistence
[INFO] ├─ Spring - Adding @o.s.s.Repository.
[INFO] └─ Spring Data - Not adding @o.j.d.a.Repository, already present.
[INFO] 
[INFO] □─ nl.daniel.dejong.inventorymanagement.infrastructure.web.ProductDefinitionDtoUtils$ProductDefinitionDto
[INFO] ├─ JPA - Adding @EmbeddableInstantiator for record.
[INFO] └─ JPA - Adding @j.p.Embeddable.
[INFO] 
[INFO] □─ nl.daniel.dejong.layoutanddesign.application.equipment.EquipmentService
[INFO] └─ Spring - Adding @o.s.s.Service.
[INFO] 
[INFO] □─ nl.daniel.dejong.layoutanddesign.domain.equipment.Equipment
[INFO] ├─ JPA - Adding @j.p.Entity.
[INFO] ├─ JPA - Adding default constructor.
[INFO] ├─ JPA - Adding nullability verification using new callback methods.
[INFO] └─ JPA - Defaulting id mapping to @j.p.EmbeddedId().
[INFO] 
[INFO] □─ nl.daniel.dejong.layoutanddesign.domain.equipment.events.EquipmentCreated
[INFO] ├─ JPA - Adding @EmbeddableInstantiator for record.
[INFO] └─ JPA - Adding @j.p.Embeddable.
[INFO] 
[INFO] □─ nl.daniel.dejong.layoutanddesign.domain.equipment.valueobjects.EquipmentId
[INFO] ├─ JPA - Adding @j.p.Embeddable.
[INFO] └─ JPA - Default constructor already present.
[INFO] 
[INFO] □─ nl.daniel.dejong.layoutanddesign.domain.equipment.valueobjects.EquipmentType
[INFO] ├─ JPA - Adding @j.p.Embeddable.
[INFO] └─ JPA - Adding default constructor.
[INFO] 
[INFO] □─ nl.daniel.dejong.layoutanddesign.infrastructure.persistence.EquipmentJpaPersistence
[INFO] ├─ Spring - Adding @o.s.s.Repository.
[INFO] └─ Spring Data - Not adding @o.j.d.a.Repository, already present.
[INFO] 
[INFO] □─ nl.daniel.dejong.orderfulfillment.application.OutboundOrderService
[INFO] └─ Spring - Adding @o.s.s.Service.
[INFO] 
[INFO] □─ nl.daniel.dejong.orderfulfillment.domain.order.OutboundOrder
[INFO] ├─ JPA - Adding @j.p.Entity.
[INFO] ├─ JPA - Adding default constructor.
[INFO] ├─ JPA - Adding nullability verification using new callback methods.
[INFO] └─ JPA - Defaulting id mapping to @j.p.EmbeddedId().
[INFO] 
[INFO] □─ nl.daniel.dejong.orderfulfillment.domain.order.events.OutboundOrderCreated
[INFO] ├─ JPA - Adding @EmbeddableInstantiator for record.
[INFO] └─ JPA - Adding @j.p.Embeddable.
[INFO] 
[INFO] □─ nl.daniel.dejong.orderfulfillment.domain.order.valueobjects.OutboundOrderId
[INFO] ├─ JPA - Adding @j.p.Embeddable.
[INFO] └─ JPA - Default constructor already present.
[INFO] 
[INFO] □─ nl.daniel.dejong.orderfulfillment.infrastructure.persistence.OutboundOrderJpaPersistence
[INFO] ├─ Spring - Adding @o.s.s.Repository.
[INFO] └─ Spring Data - Not adding @o.j.d.a.Repository, already present.
[INFO] 
[INFO] Transformed 33 type(s)

I am using the byte buddy plugin as follows:

<plugin>
    <groupId>net.bytebuddy</groupId>
    <artifactId>byte-buddy-maven-plugin</artifactId>
    <version>1.14.9</version>
    <executions>
        <execution>
            <goals>
                <goal>transform</goal> <!-- Enable the source cod
            </goals>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>org.jmolecules.integrations</groupId>
            <artifactId>jmolecules-bytebuddy</artifactId>
            <version>0.17.0</version>
        </dependency>
    </dependencies>
</plugin
odrotbohm commented 8 months ago

I cannot really reproduce this here, as all our integration tests and sample projects work fine on the first run. Can you share a reproducer? Are you using the integration though some IDE?

DanieldeJongVeldstra commented 8 months ago

For now a little information until I can get to my laptop and create reproducer.

  1. I am running the mvn clean package command via Intellij
  2. I notice when I am running the package that my ApplicationModuleTest are properly running, but if i am trying run the application afterwards (via play button in intellij) it is missing beans (annotations are not set properly).
odrotbohm commented 8 months ago

That's a known problem. IDEA currently doesn't properly invoke build plugins as part of their normal build invocation. This has been reported, for example here. It looks like other IDEs (VSCode, Eclipse) handle this appropriately. I can recommend voting for the ticket and, as a workaround, either enable IDEA delegating all build work to Maven, or explicitly run the plugin before a test execution.

DanieldeJongVeldstra commented 8 months ago

Not sure if this fully matches my problem because when I am running a maven package and I am seeing in the logs that the plugin is executed.

I have added you for now as a collaborator to my project so you can clone and see it: https://github.com/DanieldeJongVeldstra/warehouse

DanieldeJongVeldstra commented 8 months ago

Some extra information, I tried running the mvn package on my work laptop (windows) and here it worked out of the box. So this might has something to do with running it on a macbook / community edition intellij. Ill try and investigate more in the evening,

odrotbohm commented 8 months ago

Just in case you missed the remark: IDEA currently does not trigger any Maven build plugin during its standard builds. I.e. any edit to a class will require you to run the build plugins manually before a test execution or the like. There's nothing we can do about this in jMolecules.

DanieldeJongVeldstra commented 8 months ago

I do indeed not expect the intellij build action to decorate my classes automaticly (would be handy though). So maybe I explained it wrong. But on my home macbook when I run a mvn package via the sidebar in Intellij I notice that the classes that are created in my target folder are not decorated with the spring annotations. When I do the same on my work laptop (windows) I do see the annotations being set properly.

image

When I run the mvn package again than I notice that it did apply the changes to the classes. I will check later tonight if I run maven from the command line if the issue is still there or not. Will also playaround with jdk's to see if those have effect.

DanieldeJongVeldstra commented 8 months ago

I found the issue, and apparently the key factor is running a package with skipTests enabled or disabled. When I run a mvn package it seem to work fine. When I run mvn package -DskipTests=true it is not updating the files. Not sure if this is wanted behavior / can be explained.

Edit: the mvn package -DskipTests=true seems to only have this behavior when running it from IntelliJ.

Edit2: I finally found the real issue (linked to the problem you linked before) what resulted in confusing behavior. I was not aware that my editor was having the build automatically function running. By disabling this I have not seen the described issue anymore.

Thanks for the assistance!

image
odrotbohm commented 8 months ago

When you say "run", what does that mean? Invoking the command from the command line or triggering the goal from within the IDE?

EDIT: I've cloned your project, and it builds fine when doing mvn clean test. Also, mvn clean package works. I've imported the project into Eclipse and can freely change code, run tests etc.

DanieldeJongVeldstra commented 8 months ago

In general with run I meant both, sometimes executing the phase from the command line and sometimes from IntelliJ. So that was a bit confusing. But the key part was that my project was automatically build which resulted in weird behaviour.