A Java Code Generator for Pojo Builders

Overview

PojoBuilder - A Code Generator for Pojo Builders

Build Status Coverage Status

Author: Michael Karneim

Project Homepage: http://github.com/mkarneim/pojobuilder

About

The PojoBuilder Generator is a Java 6 compliant annotation processor that generates a fluent builder class for POJOs (Plain Old Java Object).

The generated builder provides

  • a fluent interface for specifying values for the pojo's properties in a DSL like manner
  • and a "build()" method for creating a new pojo instance with these values.

Here is an example of how you could use a generated pojo builder from your code:

	Contact james = new ContactBuilder()
		.withSurname("Bond")
		.withFirstname("James")
		.withEmail("[email protected]")
		.build();

Builders are quite useful, for example, to build test data, where you only want to set the relevant data properties.

For more information on

License and Dependencies

The source code located in the "src" directory is in the PUBLIC DOMAIN. For more information please read the COPYING file.

PojoBuilder is a pure code generator. It does not add any runtime dependencies to your project.

However, PojoBuilder adds the following compile-time dependency to your project, which has its own license:

Download

PojoBuilder is Open Source. The source code is available at http://github.com/mkarneim/pojobuilder. For older versions and a change log please see the release history page.

PojoBuilder binaries are available for download at Sonatype OSS Maven Repository and Maven Central.

If you don't use any build automation tool that supports maven repos, you might want to download the pojobuilder-4.2.3-jar-with-dependencies.jar to get PojoBuilder complete with all dependent libraries included.

How To Use

The PojoBuilder generator uses an annotation processor to generate pojo builders for you. You have the following options to trigger the code generation:

Annotating a Constructor

To generate a builder class for a pojo you can annotate one of its constructors with @GeneratePojoBuilder.

Let's have a look at the following example pojo:

public class Contact {
  private final String surname;
  private final String firstname;
  private String email;

  @GeneratePojoBuilder
  public Contact(String surname, String firstname) {
    this.surname = surname;
    this.firstname = firstname;
  }

  public String getEmail() {
    return email;
  }

  public void setEmail(String email) {
    this.email = email;
  }

  public String getSurname() {
    return surname;
  }

  public String getFirstname() {
    return firstname;
  }
}

The @GeneratePojoBuilder annotation tells the annotation processor to create a new Java source file with the name ContactBuilder. Have a look at ContactBuilder.java to see the generated source code.

Please note that the constructor must be public or otherwise accessible for the generated builder, e.g. if it's protected the generated builder must reside in the same package.

And also note that the constructor parameter names must match the names of the pojo's properties exactly.

An optional @ConstructorProperties annotation can be used to specify the mapping from the constructor-parameter-names to the corresponding bean-property-names on the pojo if they differ.

public class Contact {
  private final String surname;
  private final String firstname;
  private String email;

  @GeneratePojoBuilder
  @ConstructorProperties({"surname","firstname"})
  public Contact(String arg1, String arg2) {
    this.surname = arg1;
    this.firstname = arg2;
  }

  public String getEmail() {
    return email;
  }

  public void setEmail(String email) {
    this.email = email;
  }

  public String getSurname() {
    return surname;
  }

  public String getFirstname() {
    return firstname;
  }
}

Annotating the Pojo

If your pojo has no constructor (or a public default constructor), you can annotate its class with @GeneratePojoBuilder.

Let's have a look at the following example pojo:

@GeneratePojoBuilder
public class User {
  private String name;
  private char[] password;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public char[] getPassword() {
    return password;
  }

  public void setPassword(char[] password) {
    this.password = password;
  }
}

Have a look at UserBuilder.java to see the generated source code.

Annotating a Factory Method

Alternatively, if you don't have access to the pojo's source code, or if you are no fan of annotating a pojo, you can annotate a factory method:

public class UrlFactory {

  @GeneratePojoBuilder(withName="UrlBuilder", intoPackage = "samples")
  public static URL createUrl(
    String protocol, String host, int port, String file, URLStreamHandler handler)
      throws MalformedURLException {
    return new URL(protocol, host, port, file, handler);
  }
}

Have a look at UrlBuilder.java to see the generated source code.

Please note that the factory method must be public and static. The method parameter names must match the names of the pojo's properties exactly.

An optional @FactoryProperties annotation can be used to specify the mapping from the factory-method-parameter-names to the corresponding bean-property-names on the pojo if they differ.

public class FileFactory {

  @GeneratePojoBuilder(intoPackage = "samples")
  @FactoryProperties({"path"})
  public static File createFile(String arg1) {
    return new File(arg1);
  }
}

Have a look at FileBuilder.java to see the generated source code.

Directives

The following elements of @GeneratePojoBuilder can be used to configure the output of the code generation process.

  • withName=<String> specifies the pattern of the builder's name. An asterisk will be replaced with the pojos simple name. For example, the result of the pattern Fluent*Builder will become FluentContactBuilder if the pojo's name is Contact. The default pattern is *Builder.
  • withConstructor=<Visibility> Specifies the visibility of the builder's constructor. Default is Visibility.PUBLIC.
  • intoPackage=<String> specifies the package of the generated builder. An asterisk will be replaced with the pojos package. For example, the result of the pattern *.util will become com.example.util if the pojo's package is com.example. The default pattern is *.
  • withBaseclass=<Class> specifies the base class of the generated builder. The default class is Object.class.
  • withBuilderInterface=<Class> specifies the interface of the generated builder. The interface must declare exactly one type parameter and a build method with this type as return type. For an example please see Address.java, Builder.java and AddressBuilder.java. Default is Void.class, which means, that no interface should be implemented.
  • withBuilderProperties=<boolean> specifies whether the generated builder should define builder-based with-methods using the builder interface (see above). For an example please see Recipient.java, Builder.java and RecipientBuilder.java. Default is false.
  • includeProperties=<String[]> specifies which of the pojo's properties will be included into the generated builder. All properties that match any property pattern in the specified array will be included. All other non-mandatory properties will be excluded. Mandatory properties are those which are passed as constructor or factory method arguments. They will never be excluded, neither explicitly nor implicitly. For an example please see InputSourceFactory.java and InputSourceBuilder.java. Default is *.
  • excludeProperties=<String[]> specifies which of the pojo's properties will be excluded from the generated builder. All property that match any property pattern in the specified array will be excluded, except those that are mandatory. Mandatory properties are those which are passed as constructor or factory method arguments. They will never be excluded, neither explicitly nor implicitly. For an example please see CalendarFactory.java and GregorianCalendarBuilder.java. Default is the empty array.
  • withGenerationGap=<boolean> specifies whether the generation gap pattern is used. If enabled, this will generate two classes (instead of one), of which one contains the ordinary builder code, whereas the other class extends the first one and is an empty template for handwritten code. Please move it out of the generated-sources folder to prevent it from being overwritten. For examples please see Player.java, PlayerBuilder.java, and AbstractPlayerBuilder.java. Default is false.
  • withCopyMethod=<boolean> specifies whether a copy method should be generated. Use the copy method to initialize the builder's values from a given pojo instance. For an example please see TextEmail.java and TextEmailBuilder.java. Default is false.
  • withOptionalProperties=<Class> specifies whether the generated builder should define optional-based setter-methods using the specified 'Optional' type. Examples are Google Guava's com.google.common.base.Optional and java.util.Optional introduced with Java 8. Default is Void.class, which means, that no optional-based setter-methods are generated.
  • withSetterNamePattern=<String> specifies the name pattern of the generated setter-methods. An asterisk will be replaced with the property's original name. Default is with*.
  • withValidator=<Class> specifies the validator class that should be used to validate the created pojo. The class must define a validate method having one parameter that is compatible with the pojo's type. If the validation fails, the method must throw some runtime exception (or one of its subclasses). For an example please see Credentials.java, CredentialsValidator.java and CredentialsBuilder.java.
  • withFactoryMethod=<String> specifies the name of a static factory method added to the builder class which creates a builder instance. An asterisk will be replaced by the pojos simple name. For an example please see Task.java and TaskBuilder.java. Default is "" meaning not to generate this method.

Default Configuration and Meta-Annotations

Beginning with version 3, PojoBuilder supports meta-annotations. That is, you can place @GeneratePojoBuilder onto another annotation and it will be inherited.

Advantages are:

  • Common PojoBuilder directives can be shared in one place
  • The annotation can also hold directives for other libraries that support meta annotations, binding them all up into one meaningful annotation for use in your application.

The following example defines @AppPojo which can applied at a class level and encapsulates the annotations from three different sources (PojoBuilder, Lombok and JSR-305).

@GeneratePojoBuilder(withName = "Fluent*Builder")
@lombok.experimental.Value // class-level annotation from Lombok
@javax.annotation.concurrent.Immutable // class-level annotation from JSR-305
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
public @interface AppPojo {
}

This can be placed onto each of your pojos:

@AppPojo
public class Contact {
  public String name;
}

PojoBuilder will generate FluentContactBuilder based on the directives inherited from the @AppPojo annotation.

Defaults inherited from meta-annotations can be overriden by more 'local' @GeneratePojoBuilder annotations:

@AppPojo
@GeneratePojoBuilder(intoPackage = "builder")
public class Contact {
  public String name;
}

This will generate FluentContactBuilder as before but into the package builder.

Examples

The PojoBuilder wiki provides a cookbook about using the PojoBuilder Generator, e.g for building a domain-specific language for automated tests.

For some complete code examples please have a look into the src/testdata/java/samples folder.

Execution

To execute the PojoBuilder annotation processor you just need to put it into the compile-time classpath. During runtime no libraries are required since the retention policy of PojoBuilder's annotations is CLASS.

Here is a list of brief descriptions about how to run PojoBuilder with

Using Javac

The javac compiler will auto-detect the presence of PojoBuilder if pojobuilder-*.jar is included in the classpath.

For example:

javac -cp pojobuilder-4.2.3-jar-with-dependencies.jar Contact.java

will generate a ContactBuilder if Contact is annotated with @GeneratePojoBuilder.

For more information see the javac documentation.

Using Maven

Add the following to your project's pom.xml to configure the PojoBuilder annotation processor.

<dependency>
	<groupId>net.karneim</groupId>
	<artifactId>pojobuilder</artifactId>
	<version>4.2.3</version>
	<!-- 'provided' scope because this is only needed during compilation -->
	<scope>provided</scope>
</dependency>

Notes:

  • The compile phase will automatically detect and activate PojoBuilder.
  • Generated sources will appear in the standard location: ${project.build.directory}/generated-sources/annotations.
  • If you need to keep the generated sources in a specific directory outside of the target directory, then configure the generatedSourcesDirectory of the maven-compiler-plugin. See the sample Maven pom for an example.
  • If you rely on incremental compilation then you might want to use the maven processor plugin instead.
  • Eclipse users might want to install m2e-apt to have integrated support for APT-generated sources.

Using Gradle

This is a small build script that shows how to run the PojoBuilder annotation processor with Gradle.

apply plugin: 'java'

repositories {
  mavenCentral()
}

dependencies {
  compile 'net.karneim:pojobuilder:4.2.3'
}

Please note that this not only adds the PojoBuilder and its dependencies to your compile-time class path but also to your run-time class path.

Alternatively you can use the following script to add PojoBuilder only to the compile-time class path:

apply plugin: 'java'

repositories {
  mavenCentral()
}

configurations {
  codeGeneration
}

dependencies {
  codeGeneration 'net.karneim:pojobuilder:4.2.3'
  compileOnly 'net.karneim:pojobuilder:4.2.3:annotations'
}
compileJava.classpath += configurations.codeGeneration
compileTestJava.classpath += configurations.codeGeneration

In both cases the generated sources will be placed into the standard build/classes directory.

If you want to put them somewhere else, just specify the destination like this:

compileJava.options.compilerArgs += ['-s', 'src/generated/java']

The wiki contains an extended Gradle script that distinguishes completely between code generation and compilation tasks.

There is another Gradle script that enables PojoBuilder for Eclipse IDE.

Gradle 5.0

With Gradle 5.0 any annotation processor in the classpath don't get executed anymore. To make pojobuilder work again, replace the used dependency scope with annotationProcessor

dependencies {
  annotationProcessor 'net.karneim:pojobuilder:4.2.3'
}

Using Ant

Here is a code snippet of some sample ANT build script that runs the PojoBuilder annotation processor within the javac task.

    <!-- Add the required libraries into this directory. -->
    <fileset id="libs.fileset" dir="${basedir}/lib">
        <include name="*.jar" />
    </fileset>

    <path id="class.path">
        <fileset refid="libs.fileset" />
    </path>

    <target name="compile" depends="init"
            description="Compile java sources and run annotation processor">
    	<mkdir dir="${src.gen.java.dir}" />
    	<mkdir dir="${build.classes.dir}" />
    	<javac classpathref="class.path" destdir="${build.classes.dir}">
    		<src path="${src.main.java.dir}" />
    		<!-- This tells the compiler where to place the generated source files -->
    		<compilerarg line="-s ${src.gen.java.dir}"/>
    	</javac>
    </target>

Using Eclipse

You could also configure Eclipse to run the PojoBuilder annotation processor during the build cycle. It will be invoked whenever you save files that contain sources annotated with @GeneratePojoBuilder.

Do the following to enable PojoBuilder for your Eclipse project:

  • Open your project's properties dialog
  • Navigate to "Java Build Path" tree node
  • Open the "Libraries" tab
  • Add pojobuilder-4.2.3-annotations.jar to your project classpath
  • Navigate to "Java Compiler / Annotation Processing" tree node
  • Check "Enable project specific settings"
  • Check "Enable annotation processing"
  • Check "Enable processing in editor"
  • Specify the target directory for the generated code in "Generated source directory"
  • Navigate to "Java Compiler / Annotation Processing / Factory Path" tree node
  • Check "Enable project specific settings"
  • Click "Add JARs..."
  • Add pojobuiler-4.2.3-jar-with-dependencies.jar
  • Click "OK"

How To Build

If you want to compile this project's sources yourself you can use Gradle (see build.gradle).

Comments
  • cannot find symbol while building

    cannot find symbol while building

    I set up the gradle script and works fine with builder and runs Junit perfectly, however, gradle build fails with blow error, seems like they are not able to find builderclass.

    cannot find symbol
        return new UserBuilder().withId(getId()).build();
                                ^
    

    This is my gradle file, did I do anything wrong with it?

    buildscript {
        ext {
            springBootVersion = '1.1.9.RELEASE'
        }
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath('org.springframework.boot:spring-boot-gradle-plugin:1.1.9.RELEASE')
        }
    }
    
    apply plugin: 'java'
    apply plugin: 'eclipse-wtp'
    apply plugin: 'idea'
    apply plugin: 'spring-boot' 
    apply plugin: 'war'
    
    ext { 
      eclipseAptFolder = '.apt_generated'
      eclipseSettingsDir = file('.settings')
    }
    
    war {
        baseName = 'boot'
        version = '0.0.1-SNAPSHOT'
    }
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
    
    repositories {
        mavenCentral()
    }
    
    configurations {
        providedRuntime
        codeGeneration
    }
    
    dependencies {
        compile('org.springframework.boot:spring-boot-starter-web') 
        providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
        compile('mysql:mysql-connector-java:5.1.34')
        compile('org.springframework.boot:spring-boot-starter-data-jpa')
        compile('org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final') 
        compile('org.hibernate:hibernate-entitymanager')
        compile('com.h2database:h2')
        compile('cz.jirutka.validator:validator-spring:1.0.1')
        compile('org.springframework.boot:spring-boot-starter-security')
        compile('org.springframework.security.oauth:spring-security-oauth2:2.0.3.RELEASE')
        compile('org.springframework.boot:spring-boot-starter-test')
        compile('org.projectlombok:lombok:1.14.8')
        compile('com.jayway.jsonpath:json-path:0.9.1') 
        compile('com.jayway.jsonpath:json-path-assert:0.9.1') 
        compile('org.apache.commons:commons-lang3:3.2')
        compile('commons-beanutils:commons-beanutils:1.9.2')
        compile('commons-validator:commons-validator:1.4.0')
        compile('org.hibernate:hibernate-validator:5.1.3.Final')
        codeGeneration 'net.karneim:pojobuilder:3.2.0'
        compile 'net.karneim:pojobuilder:3.2.0:annotations'
    }
    
    compileJava.classpath += configurations.codeGeneration
    
    eclipse {
      jdt.file.withProperties { 
          it['org.eclipse.jdt.core.compiler.processAnnotations'] = 'enabled'
        }
        classpath {
             containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
             containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
        }
    }
    
    task wrapper(type: Wrapper) {
        gradleVersion = '1.12'
    }
    
    tasks.eclipseJdt {
      doFirst {
        def aptPrefs = 
          file("${eclipseSettingsDir}/org.eclipse.jdt.apt.core.prefs")
        aptPrefs.parentFile.mkdirs()
    
        aptPrefs.text = """\
        eclipse.preferences.version=1
        org.eclipse.jdt.apt.aptEnabled=true
        org.eclipse.jdt.apt.genSrcDir=${eclipseAptFolder}
        org.eclipse.jdt.apt.reconcileEnabled=true
        """.stripIndent()
    
        file('.factorypath').withWriter {
          new groovy.xml.MarkupBuilder(it).'factorypath' {
            project.configurations.codeGeneration.each { dep->
              factorypathentry(
                kind:'EXTJAR',
                id:dep.absolutePath,
                enabled:true,
                runInBatchMode:false
              )
            }
          }
        }
      }
    }
    
    Not a Bug 
    opened by legshort 13
  • javac crash on java 8 after adding pojobuilder

    javac crash on java 8 after adding pojobuilder

    Hi,

    after I've started using pojobuilder in a java 7 project using a java 8 jdk, and I found a reproducible issue every time the compile maven goal is executed without a prior clean.

    Don't know if a workaround is possible, I've found only a fixed report in javadoc with the same error message: http://bugs.java.com/view_bug.do?bug_id=8029145

    Anyone knows how to report a jdk bug to oracle?

    Stacktrace for reference:

    An exception has occurred in the compiler (1.8.0_20). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parad
    e for duplicates. Include your program and the following diagnostic in your report.  Thank you.
    java.lang.IllegalStateException: endPosTable already set
            at com.sun.tools.javac.util.DiagnosticSource.setEndPosTable(DiagnosticSource.java:136)
            at com.sun.tools.javac.util.Log.setEndPosTable(Log.java:350)
            at com.sun.tools.javac.main.JavaCompiler.parse(JavaCompiler.java:667)
            at com.sun.tools.javac.main.JavaCompiler.parseFiles(JavaCompiler.java:950)
            at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.<init>(JavacProcessingEnvironment.java:892)
            at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.next(JavacProcessingEnvironment.java:921)
            at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1187)
            at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
            at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
            at com.sun.tools.javac.main.Main.compile(Main.java:523)
            at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
            at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
            at org.codehaus.plexus.compiler.javac.JavaxToolsCompiler.compileInProcess(JavaxToolsCompiler.java:126)
            at org.codehaus.plexus.compiler.javac.JavacCompiler.performCompile(JavacCompiler.java:169)
            at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:785)
            at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:129)
            at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:106)
            at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
            at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
            at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
            at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
            at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
            at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
            at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
            at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:317)
            at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:152)
            at org.apache.maven.cli.MavenCli.execute(MavenCli.java:555)
            at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:214)
            at org.apache.maven.cli.MavenCli.main(MavenCli.java:158)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:483)
            at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
            at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
            at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
    [INFO] -------------------------------------------------------------
    [ERROR] COMPILATION ERROR : 
    [INFO] -------------------------------------------------------------
    [ERROR] An unknown compilation problem occurred
    [INFO] 1 error
    [INFO] -------------------------------------------------------------
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD FAILURE
    [INFO] ------------------------------------------------------------------------
    
    Accepted 
    opened by gionn 12
  • Java 9 error java.lang.NoClassDefFoundError: javax/annotation/Generated

    Java 9 error java.lang.NoClassDefFoundError: javax/annotation/Generated

    Hello. I am trying to use pojobuilder 4.1.0 with Java 9. Please help me with error. I used example https://github.com/mkarneim/pojobuilder#annotating-a-constructor

    public class Contact {
        private final String surname;
        private final String firstname;
        private String email;
    
        @GeneratePojoBuilder
        public Contact(String surname, String firstname) {
            this.surname = surname;
            this.firstname = firstname;
        }
       ...
    

    I am building maven on java 9.

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.7.0</version>
                    <configuration>
                        <source>9</source>
                        <target>9</target>
                        <showWarnings>true</showWarnings>
                        <showDeprecation>true</showDeprecation>
                    </configuration>
                </plugin>
    

    Error:

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project pojobuilder-simple: Compilation failure
    [ERROR] 
    [ERROR] java.lang.NoClassDefFoundError: javax/annotation/Generated
    [ERROR] at net.karneim.pojobuilder.sourcegen.BuilderSourceGenerator.generateSource(BuilderSourceGenerator.java:84)
    [ERROR] at net.karneim.pojobuilder.sourcegen.BuilderSourceGenerator.generateSource(BuilderSourceGenerator.java:57)
    [ERROR] at net.karneim.pojobuilder.processor.AnnotationProcessor.generateBuilderImpl(AnnotationProcessor.java:238)
    [ERROR] at net.karneim.pojobuilder.processor.AnnotationProcessor.generateSources(AnnotationProcessor.java:218)
    [ERROR] at net.karneim.pojobuilder.processor.AnnotationProcessor.process(AnnotationProcessor.java:139)
    [ERROR] at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:968)
    [ERROR] at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:884)
    [ERROR] at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.access$2200(JavacProcessingEnvironment.java:108)
    [ERROR] at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1206)
    [ERROR] at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1315)
    [ERROR] at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1246)
    [ERROR] at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:922)
    [ERROR] at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:100)
    [ERROR] at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:142)
    [ERROR] at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:96)
    [ERROR] at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:90)
    [ERROR] at org.codehaus.plexus.compiler.javac.JavaxToolsCompiler.compileInProcess(JavaxToolsCompiler.java:126)
    [ERROR] at org.codehaus.plexus.compiler.javac.JavacCompiler.performCompile(JavacCompiler.java:174)
    [ERROR] at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:1075)
    [ERROR] at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:168)
    [ERROR] at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
    [ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:207)
    [ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    [ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    [ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
    [ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
    [ERROR] at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
    [ERROR] at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
    [ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
    [ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
    [ERROR] at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
    [ERROR] at org.apache.maven.cli.MavenCli.execute(MavenCli.java:863)
    [ERROR] at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
    [ERROR] at org.apache.maven.cli.MavenCli.main(MavenCli.java:199)
    [ERROR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    [ERROR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    [ERROR] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    [ERROR] at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    [ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
    [ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
    [ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
    [ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
    [ERROR] at org.codehaus.classworlds.Launcher.main(Launcher.java:47)
    [ERROR] Caused by: java.lang.ClassNotFoundException: javax.annotation.Generated
    [ERROR] at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:466)
    [ERROR] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:563)
    [ERROR] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
    [ERROR] ... 43 more
    [ERROR] -> [Help 1]
    [ERROR] 
    [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
    [ERROR] Re-run Maven using the -X switch to enable full debug logging.
    [ERROR] 
    [ERROR] For more information about the errors and possible solutions, please read the following articles:
    [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
    
    Bug 
    opened by vostapets 11
  • copy only not set fields

    copy only not set fields

    Hi, I would like to see something similar to copy() but with a slight difference. Let me describe the usecase: I want to define some testdata so I use a builder on my jpa entitys. I would like to keep my testdata-definition separat and just want to define the attributes currently necessary for the testcase, e.g. for an article I maybe just want to specify its articlenumber (key) and measurements but the weight is not needed. In the testcase I'd like to define a builder with desired values, then my testframework should lookup the entity by it's key (if present) and just modify the values set in the builder (example above: keep weigth of the article as is). If no article is found a new one will be created and weight is empty then. Of course the lookup of JPA-entitys and persisting them is not part of my request to pojobuilder, just part of usecasedescription.

    Best way to achieve this might be to have a buildWithBase(T t) or something like this which uses the passed in object (if not null) instead a new instance of T to set the builder-values. What do you think about that? Or is there already a way to achive this I didn't notice?

    best regards Ralf

    opened by blackfoxoh 10
  • Allow a custom method name prefix

    Allow a custom method name prefix

    This contribution allows to provide a custom method name prefix instead of "with"

    IMHO "with" is obsolete, as it is clear when using a builder. Also it is too much redundancy.

    How to set a custom prefix or remove it.

    There are two ways.

    1. Create and add a pojobuilder.properties file to your classpath. The property file should contains the key net.karneim.pojobuilder.methodnameprefix=xx
    2. Annotation Processor Arguments (-A parameter) http://docs.oracle.com/javase/7/docs/technotes/guides/apt/GettingStarted.html add argument -Anet.karneim.pojobuilder.methodnameprefix=xx to annotation processor.

    Maven Example:

             <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                   <compilerArgument>-Anet.karneim.pojobuilder.methodnameprefix=zzz</compilerArgument>
                   <!-- alternative for no prefix -->
                   <compilerArgument>-Anet.karneim.pojobuilder.methodnameprefix</compilerArgument>
                </configuration>
             </plugin>
    

    Depending on the eclipse and m2e annotation processor setup this setting will be also used by eclipse.

    opened by Vad1mo 10
  • Overload withXxx(XxxBuilder builder)

    Overload withXxx(XxxBuilder builder)

    The API would be a little more nice and readable if the generated builder accepted other builders as parameters. If you added a Builder interface, then you could use this are the parameter in the overloaded method.

    The overloaded method at its simplest could call build() saving it bloating the end-user code, or do something more clever like delay calling it until the host builder is built.

    Accepted 
    opened by BinaryTweedDeej 10
  • Mixed maven scala/java build fails if java sources refer to Scala classes

    Mixed maven scala/java build fails if java sources refer to Scala classes

    PojoBuilder fails if java sources refer to Scala classes built in same project (The java source file where it is failing contains no @GeneratePojoBuilder annotation.

    Maven phases:

    generate-sources => here pojo builder scans the java sources process-resources => here scala compiles mixed java and scala project compile => here javac compiles the rest

    Moving scala compilation to the initialize phase works (pojo builder has all the scala built classes) but i'm not able to use generated sources from scala

    I don't know if processing sources with missing types is an annotation processor limitation or a PojoBuilder one.

    The maven configuration for a mixed scala/java project i'm using is this one:

    <plugin>
        <groupId>net.alchim31.maven</groupId>
        <artifactId>scala-maven-plugin</artifactId>
        <version>3.2.2</version>
        <inherited>true</inherited>
        <executions>
            <execution>
                <id>scala-compile-first</id>
                <phase>process-resources</phase>
                <goals>
                    <goal>add-source</goal>
                    <goal>compile</goal>
                </goals>
            </execution>
            <execution>
                <id>scala-test-compile</id>
                <phase>process-test-resources</phase>
                <goals>
                    <goal>testCompile</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

    This is the configuration i'm using to perform scala build in initialize phase as a workaround

    <plugin>
        <groupId>net.alchim31.maven</groupId>
        <artifactId>scala-maven-plugin</artifactId>
        <version>3.2.2</version>
        <inherited>true</inherited>
        <executions>
            <execution>
                <id>scala-compile-first</id>
                <phase>initialize</phase>
                <goals>
                    <goal>add-source</goal>
                    <goal>compile</goal>
                </goals>
            </execution>
            <execution>
                <id>scala-test-compile</id>
                <phase>process-test-resources</phase>
                <goals>
                    <goal>testCompile</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    
    Not a Bug 
    opened by andrea-rockt 9
  • Add a getter for every with-Builder to allow to change values on a prodefined structure

    Add a getter for every with-Builder to allow to change values on a prodefined structure

    Hi @mkarneim,

    I would like to provide a valid default builder structure with multiple levels for everybody. If you have to adjust a certain value with the structure, I would be nice to be able to access the deeper levels directly by using some getter for the nested builders.

    But this would require to return the correct builder instead of Builder<T> which maybe hard to determine, wouldn't it?

    Here is my example:

        public static GetAccountBuilder $validGetAccount() {
            return new GetAccountBuilder().withRequest(
                    new GetAccountRequestBuilder()
                            .withClient(Client.ABC.clientId)
                            .withRequestTimestamp(toXmlGregorianCalendar(DateTime.now()))
                            .withUserID("1234567")
                );
        }
    

    Now I would like to change the userId for another test case:

    any($validGetAccount().getRequestBuilder().withUserID("987654")
    

    Do you have any idea if this could be generated because otherwise I have to create a lot of builders myself.

    Cheers, Andreas

    Question 
    opened by aaschmid 9
  • Builder class not created

    Builder class not created

    Hi, pojobuilder is exactly what I was looking for but I seems not creating builder class.

    I am using JDK8 and @lombok, I annotated @GeneratePojoBuilder at the class level and nothing happens. I don't see any further instructions at README.md.

    By the way, thanks for this great library.

    Not a Bug 
    opened by legshort 8
  • Publish 3.2.0 to Sonatype OSS Maven Repo and Maven Central

    Publish 3.2.0 to Sonatype OSS Maven Repo and Maven Central

    Currently I can't publish the new release since somehow magically the PB staging repo has disappeared from the Sonatype OSS Maven repo. I have contacted Sonatype about this.

    When this is fixed I will publish PB 3.2.0.

    opened by mkarneim 8
  • Use initialized fields when creating object

    Use initialized fields when creating object

    We have multiple objects like

    class Foo {
        private List<A> as = new ArrayList<>();
        private List<B> bs = new ArrayList<>();
        private Bar bar = new Bar();
    
        @GeneratePojoBuilder
        public Foo(List<A> as, List<B> bs, Bar bar) {
            this.as = as;
            this.bs = bs;
            this.bar = bar;
        }
    }
    

    Especially for collections, we don't want to handle null objects.

    When creating such object with PojoBuilder the problem is that field initializations are not taken into account since builder uses constructor directly with all fields set by builder or null. I can work around this by using copy feature like new FooBuilder().copy(new Foo()) but it's not very convenient to say this everywhere.

    Is it possible that builder actually would use initial values for fields?

    Question 
    opened by jukkasi 7
  • Generated copy() method does not copy all fields

    Generated copy() method does not copy all fields

    PojoBuilder generates copy() method with annotation @GeneratePojoBuilder(withCopyMethod = true). It may skip generation of this method if all pojo properties are final, but should work for all non-final properties. Right? Wrong.

    If your class defines custom accessor methods with Optionals, like this one:

    @GeneratePojoBuilder(withCopyMethod = true)
    public class Flight {
        private String flightNumber;
    
        private Integer journeyMins;
    
        private Integer numStops;
    
        void setFlightNumber(String flightNumber) {
            this.flightNumber = flightNumber;
        }
    
        void setJourneyMins(int journeyMins) {
            this.journeyMins = journeyMins;
        }
    
        void setNumStops(int numStops) {
            this.numStops = numStops;
        }
    
        public String getFlightNumber() {
            return flightNumber;
        }
    
        public Optional<Integer> getJourneyMinsOptional() {
            return Optional.ofNullable(journeyMins);
        }
    
        public Integer getJourneyMins() {
            return journeyMins;
        }
    
        public Optional<Integer> getNumStopsOptional() {
            return Optional.ofNullable(numStops);
        }
    }
    

    PojoBuilder will generate this copy method:

     /**
         * Copies the values from the given pojo into this builder.
         *
         * @param pojo
         * @return this builder
         */
        public FlightBuilder copy(Flight pojo) {
            withFlightNumber(pojo.getFlightNumber());
            return self;
        }
    

    Two properties are missing even though "with" methods are generated properly.

    Please fix it.

    opened by jza70 0
  • [SECURITY] Fix Temporary Directory Hijacking or Information Disclosure Vulnerability

    [SECURITY] Fix Temporary Directory Hijacking or Information Disclosure Vulnerability

    Security Vulnerability Fix

    This pull request fixes either 1.) Temporary Directory Hijacking Vulnerability, or 2.) Temporary Directory Information Disclosure Vulnerability, which existed in this project.

    Preamble

    The system temporary directory is shared between all users on most unix-like systems (not MacOS, or Windows). Thus, code interacting with the system temporary directory must be careful about file interactions in this directory, and must ensure that the correct file permissions are set.

    This PR was generated because the following chain of calls was detected in this repository in a way that leaves this project vulnerable. File.createTempFile(..) -> file.delete() -> either file.mkdir() or file.mkdirs().

    Impact

    This vulnerability can have one of two impacts depending upon which vulnerability it is.

    1. Temporary Directory Information Disclosure - Information in this directory is visable to other local users, allowing a malicious actor co-resident on the same machine to view potentially sensitive files.
    2. Temporary Directory Hijacking Vulnerability - Same impact as 1. above, but also, ther local users can manipulate/add contents to this directory. If code is being executed out of this temporary directory, it can lead to local priviledge escalation.

    Temporary Directory Hijacking

    This vulnerability exists because the return value from file.mkdir() or file.mkdirs() is not checked to determine if the call succeeded. Say, for example, because another local user created the directory before this process.

    File tmpDir = File.createTempFile("temp", ".dir"); // Attacker knows the full path of the directory that will be later created
    // delete the file that was created
    tmpDir.delete(); // Attacker sees file is deleted and begins a race to create their own directory before the java code.
    // and makes a directory of the same name
    // SECURITY VULNERABILITY: Race Condition! - Attacker beats java code and now owns this directory
    tmpDir.mkdirs(); // This method returns 'false' because it was unable to create the directory. No exception is thrown.
    // Attacker can write any new files to this directory that they wish.
    // Attacker can read any files created within this directory.
    

    Other Examples

    Temporary Directory Information Disclosure

    This vulnerability exists because, although the return values of file.mkdir() or file.mkdirs() are correctly checked, the permissions of the directory that is created follows the default system uname settings. Thus, the directory is created with everyone-readable permissions. As such, any files/directories written into this directory are viewable by all other local users on the system.

    File tmpDir = File.createTempFile("temp", ".dir");
    tmpDir.delete();
    if (!tmpDir.mkdirs()) { // Guard correctly prevents temporary directory hijacking, but directory contents are everyone-readable.
        throw new IOException("Failed to create temporary directory");
    }
    

    Other Examples

    The Fix

    The fix has been to convert the logic above to use the following API that was introduced in Java 1.7.

    File tmpDir = Files.createTempDirectory("temp dir").toFile();
    

    The API both created the directory securely, ie with a random, non-conflicting name, with directory permissions that only allow the currently executing user to read or write the contents of this directory.

    :arrow_right: Vulnerability Disclosure :arrow_left:

    :wave: Vulnerability disclosure is a super important part of the vulnerability handling process and should not be skipped! This may be completely new to you, and that's okay, I'm here to assist!

    First question, do we need to perform vulnerability disclosure? It depends!

    1. Is the vulnerable code only in tests or example code? No disclosure required!
    2. Is the vulnerable code in code shipped to your end users? Vulnerability disclosure is probably required!

    Vulnerability Disclosure How-To

    You have a few options options to perform vulnerability disclosure. However, I'd like to suggest the following 2 options:

    1. Request a CVE number from GitHub by creating a repository-level GitHub Security Advisory. This has the advantage that, if you provide sufficient information, GitHub will automatically generate Dependabot alerts for your downstream consumers, resolving this vulnerability more quickly.
    2. Reach out to the team at Snyk to assist with CVE issuance. They can be reached at the Snyk's Disclosure Email.

    Detecting this and Future Vulnerabilities

    This vulnerability was automatically detected by GitHub's LGTM.com using this CodeQL Query.

    You can automatically detect future vulnerabilities like this by enabling the free (for open-source) GitHub Action.

    I'm not an employee of GitHub, I'm simply an open-source security researcher.

    Source

    This contribution was automatically generated with an OpenRewrite refactoring recipe, which was lovingly hand crafted to bring this security fix to your repository.

    The source code that generated this PR can be found here: UseFilesCreateTempDirectory

    Opting-Out

    If you'd like to opt-out of future automated security vulnerability fixes like this, please consider adding a file called .github/GH-ROBOTS.txt to your repository with the line:

    User-agent: JLLeitschuh/security-research
    Disallow: *
    

    This bot will respect the ROBOTS.txt format for future contributions.

    Alternatively, if this project is no longer actively maintained, consider archiving the repository.

    CLA Requirements

    This section is only relevant if your project requires contributors to sign a Contributor License Agreement (CLA) for external contributions.

    It is unlikely that I'll be able to directly sign CLAs. However, all contributed commits are already automatically signed-off.

    The meaning of a signoff depends on the project, but it typically certifies that committer has the rights to submit this work under the same license and agrees to a Developer Certificate of Origin (see https://developercertificate.org/ for more information).

    - Git Commit Signoff documentation

    If signing your organization's CLA is a strict-requirement for merging this contribution, please feel free to close this PR.

    Sponsorship & Support

    This contribution is sponsored by HUMAN Security Inc. and the new Dan Kaminsky Fellowship, a fellowship created to celebrate Dan's memory and legacy by funding open-source work that makes the world a better (and more secure) place.

    This PR was generated by Moderne, a free-for-open source SaaS offering that uses format-preserving AST transformations to fix bugs, standardize code style, apply best practices, migrate library versions, and fix common security vulnerabilities at scale.

    Tracking

    All PR's generated as part of this fix are tracked here: https://github.com/JLLeitschuh/security-research/issues/10

    opened by JLLeitschuh 0
  • Problem using 4.2.3 with Java7

    Problem using 4.2.3 with Java7

    With Java7 PB 4.2.3 does not produce any generated files and javac stops without any message. Java8 in contrast works as expected. In the demo below I used the example User.java.

    Demo with Java7 image

    Demo with Java8 image

    opened by Rotznase 0
  • Add withSetterVarargs parameter.

    Add withSetterVarargs parameter.

    If the POJO has a setter setFoos(Foo[] foos), I'd like the option to generate setter methods in the builder with withFoos(Foo... foos).

    This would allow for a more fluent creation of objects.

    opened by NaridaL 0
  • Improve performance by removing 'self' field

    Improve performance by removing 'self' field

    I tested this using the JMH test cases return this; instead of the default return self; and saw very notable increase in performance (and decrease in heap allocation). I think the JVM doesn't know self will point to itself so reserves enough space for a second full builder object.

    1 Use of self should be constrained to withGenerationGap. 2 Use of self vs casting should be compared (not done here)

    PojobuilderPerformance.constructManually                                                 thrpt            243.662           ops/s
    PojobuilderPerformance.constructViaBuilder_private                                       thrpt            145.929           ops/s
    PojobuilderPerformance.constructViaBuilder_shared                                        thrpt            131.137           ops/s
    PojobuilderPerformance.constructViaBuilder_threadlocal                                   thrpt            153.278           ops/s
    PojobuilderPerformance.constructViaThisBuilder_private                                   thrpt            226.686           ops/s
    PojobuilderPerformance.constructViaThisBuilder_shared                                    thrpt            141.562           ops/s
    
    opened by drekbour 1
  • Use sneaky-throws in clone() method

    Use sneaky-throws in clone() method

    Currently PB clone() wraps the (checked) CloneNotSupportedException with InternalError. As of Java 8, the following "sneaky throws" allows the code to propagate the checked exception directly.

      @Override
      @GwtIncompatible
      public Object clone() {
        return _clone();
      }
    
      private <T extends Throwable> Object _clone() throws T {
        try {
          BookBuilder result = (BookBuilder)super.clone();
          result.self = result;
          return result;
        } catch (CloneNotSupportedException e) {
          throw (T)e; // "Sneaky-throws" CloneNotSupportedException
        }
      }
    

    It's also worth discussing if clone() should be suppressing at all. It's fine for but() to do this but I don't follow why we're trying to reduce the public method.

    opened by drekbour 0
Releases(v4.3.0)
Owner
Michael Karneim
Michael Karneim
A code generator to create Android ContentProvider

DatabaseCodeGenerator This project is a code generator written in Java used to generate Android code. Given a database schema JSON definition file, it

Foxykeep 297 Nov 25, 2022
Bad Apple!! AA Generator

BadAppleK Bad Apple!! ASCII Art Generator for macOS Terminal. Youtube: https://www.youtube.com/watch?v=Iv8jbo4KDFo How to execute on your environment.

kuu(Fumiya Kume) 18 Jul 25, 2022
StoryGen - A simple story generator (or it will be eventually) to learn Kotlin

StoryGen A simple story generator (or it will be eventually) to learn Kotlin. To

Markus Reinke 0 Jan 7, 2022
A Java API for generating .java source files.

JavaPoet JavaPoet is a Java API for generating .java source files. Source file generation can be useful when doing things such as annotation processin

Square 10k Jan 2, 2023
Pure Java code generation tool for generating a fully functional ContentProvider for Android.

RoboCoP RoboCoP is a Java library that can generate a fully-functional ContentProvider from a simple JSON schema file. Get the latest version from our

Rain 246 Dec 29, 2022
:package: Android Parcelables made easy through code generation.

Parceler Have a question? Ask it on StackOverflow. Found an issue? Please report it. In Android, Parcelables are a great way to serialize Java Objects

John Ericksen 3.6k Dec 27, 2022
A custom view styling library for Android that generates the obtainStyledAttributes() and TypedArray boilerplate code for you.

DEPRECATED This project is no longer maintained. Consider using https://github.com/airbnb/paris Barber Barber is your personal custom view stylist. Si

Zac Sweers 716 Dec 30, 2022
Annotation Processor for generating Parcelable code

ParcelablePlease An AnnotationProcessor for generating Android Parcelable boilerplate code. See this blog entry for comparison with other parcel libra

Hannes Dorfmann 260 Mar 31, 2022
Codegeneration tool for isomorphic server and mobile Go apps with gRPC & Protobuf. Share code between your backend, Android & iOS app! :sun_with_face:

Anakin Codegeneration tool for isomorphic server and mobile Go apps with gRPC & Protobuf. Share code between your backend, Android & iOS app! Descript

Kirill Biakov 17 Jun 25, 2020
A small tool to help you generate android projects that have a base code.

Volt Project A small tool to help you generate android projects that have a base code. Usage Change project in base directory. python volt-gen.py <pac

Victor Varenik 3 Feb 2, 2022
Kotlin code generation for commercetools platform type-safe product-types, reference expansion and custom fields

Kotlin code generation for commercetools platform type-safe product-types, reference expansion and custom fields

null 8 Dec 15, 2022
Mirai-device-generator - Mirai Device Generator with kotlin

Mirai Device Generator Mirai DeviceInfo 生成器 作为插件运行时会提供 BotConfigurationAlterer 服

cssxsh 46 Jan 1, 2023
A code generator to create Android ContentProvider

DatabaseCodeGenerator This project is a code generator written in Java used to generate Android code. Given a database schema JSON definition file, it

Foxykeep 297 Nov 25, 2022
Exposed spring integration and code generator for dsl interface

Infra-ORM 欢迎使用 Infra-ORM, 这是一个基于 Exposed 的 ORM 框架,可以和 Spring Boot 集成良好,如果你是 Kotlin 开发者,推荐你试试 Exposed, 配合 Infra-ORM 可以给你带来最佳的开发体验。 为什么造这个轮子? Exposed 提供

Red Sparrow 1 Jan 2, 2022
Auto-pipeline: a source code generator, it will generate your component's pipeline

auto-pipeline ?? auto-pipeline is a source code generator, it will generate your

Zava 106 Dec 20, 2022
LiteHttp is a simple, intelligent and flexible HTTP framework for Android. With LiteHttp you can make HTTP request with only one line of code! It could convert a java model to the parameter and rander the response JSON as a java model intelligently.

Android network framework: LiteHttp Tags : litehttp2.x-tutorials Website : http://litesuits.com QQgroup : 42960650 , 47357508 Android网络通信为啥子选 lite-htt

马天宇 829 Dec 29, 2022
ArchGuard Scanner for scan Git change history, scan source code by Chapi for Java, TypeScript, Kotlin, Go..、Java bytecode use for JVM languages, scan Jacoco test coverage.

Arch Scanner Requirements: JDK 12 Scanner: scan_git - Git commit history scan scan_jacoco - Jacoco scan scan_bytecode - for JVM languages known issues

ArchGuard 27 Jul 28, 2022
The Kotlin fake data generator library!

Fakeit This library is a port of the Ruby gem Faker. It generates realistic fake data — like names, emails, dates, countries — for a variety of scenar

Moove It 517 Nov 20, 2022
Bad Apple!! AA Generator

BadAppleK Bad Apple!! ASCII Art Generator for macOS Terminal. Youtube: https://www.youtube.com/watch?v=Iv8jbo4KDFo How to execute on your environment.

kuu(Fumiya Kume) 18 Jul 25, 2022
Ktor OpenAPI Spec Generator

Kompendium What is Kompendium Kompendium is intended to be a minimally invasive OpenApi Specification generator for Ktor. Minimally invasive meaning t

Backbone 91 Jan 4, 2023