mkarneim / pojobuilder

A Java Code Generator for Pojo Builders
Other
334 stars 44 forks source link

"withGenerationGap=true" keeps generating the concrete Class even if i moved this class outside the generation folder #151

Closed teemueller closed 6 years ago

teemueller commented 6 years ago

Hello,

when I activate "withGenerationGap" on my Pojo, PojoBuilder keeps generating the concrete Class on subsequent Maven builds even if i moved this class outside the generation folder.

Am I doing something wrong?

Thanks in advance.

Torsten

mkarneim commented 6 years ago

Which versions (PB, jdk, maven) are you using? Can you please add your pom and some java code here?

teemueller commented 6 years ago

We use the following Versions:

JDK: jdk1.8.0_131 PojoBuilder: 4.2.0 Maven: 3.3.9

I usually build with mvn clean [test-compile|verify|install].

Snippet from our Master pom.xml:

<properties>
  <maven.compiler.source>1.8</maven.compiler.source>
  <maven.compiler.target>1.8</maven.compiler.target>

  <maven-compiler-plugin.version>3.2</maven-compiler-plugin.version>
  <maven-processor-plugin.version>2.2.4</maven-processor-plugin.version>

  <pojobuilder.version>4.2.0</pojobuilder.version>
</properties>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>net.karneim</groupId>
      <artifactId>pojobuilder</artifactId>
      <version>${pojobuilder.version}</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<build>
  <pluginManagement>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven-compiler-plugin.version}</version>
        <configuration>
          <optimize>true</optimize>
          <compilerArgument>-proc:none</compilerArgument>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.bsc.maven</groupId>
        <artifactId>maven-processor-plugin</artifactId>
        <version>${maven-processor-plugin.version}</version>
      </plugin>
    </plugins>
  </pluginManagement>
</build>

Snippet from our Child pom.xml:

<dependencies>
  <dependency>
    <groupId>net.karneim</groupId>
    <artifactId>pojobuilder</artifactId>
  </dependency>
</dependencies>

<build>
  <plugins>
    <plugin>
      <groupId>org.bsc.maven</groupId>
      <artifactId>maven-processor-plugin</artifactId>
      <executions>
        <execution>
          <id>generate-sources_fluent-builder</id>
          <goals>
            <goal>process</goal>
        </goals>
        <phase>generate-test-sources</phase>
        <configuration>
          <processors>
            <processor>net.karneim.pojobuilder.processor.AnnotationProcessor</processor>
          </processors>
          <outputDirectory>${project.build.directory}/generated-test-sources/builder</outputDirectory>
        </configuration>
      </execution>
    </executions>
    <dependencies>
      <dependency>
        <groupId>net.karneim</groupId>
        <artifactId>pojobuilder</artifactId>
        <version>${pojobuilder.version}</version>
        </dependency>
      </dependencies>
    </plugin>
  </plugins>
</build>

Entity class:

@GeneratePojoBuilder(withFactoryMethod = "adressat", withBuilderInterface = Builder.class, withBuilderProperties = true)
public class Adressat extends BaseAuditEntity implements Serializable {
}

Torsten

teemueller commented 6 years ago

I created a small mavenized project which reproduces the behaviour even with the newest versions of pojobuilder and the related Maven plugins.

pojobuilder-quickstart.zip

mkarneim commented 6 years ago

Alright, I will have a look into your zip file.

In the meanwhile may I ask you to copy the following project setup and to tell me if it works for you?

From the command line, please run the following command:

man clean compile test

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>net.karneim</groupId>
    <artifactId>pojobuilder-samples</artifactId>
    <version>1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>PojoBuilder samples</name>

    <description>Sample usages of PojoBuilder</description>

    <dependencies>
        <dependency>
            <groupId>net.karneim</groupId>
            <artifactId>pojobuilder</artifactId>
            <version>[4.2.0,)</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <optimize>true</optimize>
                    <compilerArgument>-proc:none</compilerArgument>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.bsc.maven</groupId>
                <artifactId>maven-processor-plugin</artifactId>
                <configuration>
                    <processors>
                        <processor>net.karneim.pojobuilder.processor.AnnotationProcessor</processor>
                    </processors>
                    <outputDirectory>${basedir}/src/generated/java</outputDirectory>
                </configuration>
                <executions>
                    <execution>
                        <id>process</id>
                        <goals>
                            <goal>process</goal>
                        </goals>
                        <phase>process-sources</phase>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

src/main/java/sample/Contact.java

package sample;

import net.karneim.pojobuilder.GeneratePojoBuilder;

@GeneratePojoBuilder(withGenerationGap=true)
public class Contact {
  public String name;

  @Override
  public String toString() {
    return "Contact [name=" + name + "]";
  } 
}

src/main/java/sample/ContactBuilder

package sample;

import javax.annotation.Generated;

/**
 * The {@link ContactBuilder} is a Builder for {@link Contact} objects.
 * <p> ATTENTION:
 *     This class has been generated.
 *     If you want to ADD HANDWRITTEN CODE,
 *     please MOVE THIS FILE out of the generated-sources folder
 *     in order to prevent it from being overwritten by the
 *     PojoBuilder generator!
 * </p>
 */
@Generated("PojoBuilder")
public class ContactBuilder extends AbstractContactBuilder {

  /**
   * Creates a new {@link ContactBuilder}.
   */
  public ContactBuilder() {
  }
}

src/test/java/sample/ContactTest.java

package sample;

import org.junit.Test;
import static org.junit.Assert.*;

public class ContactTest {
  @Test
  public void test() {
    ContactBuilder underTest = new ContactBuilder();
    Contact act = underTest.withName("blah").build();
    assertEquals("blah",act.name);  
  }
}
mkarneim commented 6 years ago

Alright, I've had a look into your reproducer project zip. Thank you for this, since this made it a lot easier for me to find the cause of your issue.

However, I had to make an assumption, so please tell me if I'm wrong: since you configured the "generate-sources_fluent-builder" execution to be invoked during the phase "generate-test-sources" I guess you wanted the builders to be generated as test artifacts so that they are not part of the production classes. Is that correct?

If so, that means: 1) You have to move the "@GeneratePojoBuilder" annotation from the production code to the test code (or otherwise the annotation processor runs on the wrong source tree). 2) You have to move the "manual" part of the generation gap classes into the test source tree, specifically "TolkienCharacterBuilder" has to go into "src/test/java/examples/testing/domain/lotr". 3) You have to set the maven-processor-plugin goal to "process-test" (or otherwise the compiler will try to compile "TolkienCharacterBuilder" before its superclass "AbstractTolkienCharacterBuilder" has been generated):

...
<id>pojobuilder_generate-test-sources</id>
  <goals>
    <goal>process-test</goal>
  </goals>
  <phase>generate-test-sources</phase>
  <configuration>
...

For 1), you need to remove the "@GeneratePojoBuilder" annotations from your pojos completely, and instead place them on some factory methods that must be part of the test source tree. For example:

src/test/java/examples/testing/domain/lotr/PojoFactory.java

package examples.testing.domain.lotr;
import net.karneim.pojobuilder.GeneratePojoBuilder;

public class PojoFactory {
  @GeneratePojoBuilder(withFactoryMethod = "tolkienCharacter", withGenerationGap = true)
  public static TolkienCharacter createTolkienCharacter(Race race, String name, int age) {
    return new TolkienCharacter(race, name, age);
  }

  @GeneratePojoBuilder(withFactoryMethod = "race")
  public static Race createRace(String name) {
    return new Race(name);
  }
}

Of course this poses some additional work, but its benefit is that you can separate test code from production code completely.

Here is the fixed version of your project zip: pojobuilder-quickstart-fixed.zip

teemueller commented 6 years ago

Thanks a lot. I will follow your advise. Consider this issue as solved.