Skip to content
/ grains Public

The "Grains" Java framework generates thread-safe, versionable objects.

License

Notifications You must be signed in to change notification settings

cambecc/grains

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Grains

... is a small Java framework that helps you make immutable, thread-safe, versionable objects. Spend less time on boring boilerplate code and more time solving problems.

  1. Create an interface with getters:

    @GrainSchema
    public interface Order {
    
        String getProduct();
    
        int getQuantity();
    }
  2. Run the Grains Maven plugin.

  3. Use the generated Factory, Builder, and Grain classes:

    OrderBuilder builder = OrderFactory.newBuilder();
    builder.setProduct("apples");
    builder.setQuantity(13);
    OrderGrain order = builder.build();
        
    System.out.println(order instanceof Order);  // prints: true
    System.out.println(order.getProduct());      // prints: apples
        
    System.out.println(order instanceof Map);    // prints: true
    System.out.println(order.get("quantity"));   // prints: 13
    System.out.println(order.entrySet());        // prints: [product=apples, quantity=13]
        
    OrderGrain changed = order.withQuantity(9);  // immutable :)
    System.out.println(changed);                 // prints: {product=apples, quantity=9}
    System.out.println(order);                   // prints: {product=apples, quantity=13}
        
    changed = changed.with("RMA", "9928");       // extensible and versionable :)
    System.out.println(changed);                 // prints: {product=apples, quantity=9, RMA=9928}

Serialization

Jackson serialization to JSON, Smile, YAML, etc. (with the grains-jackson library):

    ObjectMapper mapper = JacksonTools.newGrainsObjectMapper();

    String json = mapper.writeValueAsString(order);
    OrderGrain restored = mapper.readValue(json, OrderGrain.class);

    System.out.println(json);                    // prints: {"product":"apples","quantity":13}
    System.out.println(restored.equals(order));  // prints: true

Kryo serialization (with the grains-kryo library):

    Kryo kryo = KryoTools.newGrainsKryo();

    Output output = new Output(1024);
    kryo.writeClassAndObject(output, order);
    output.close();

    Input input = new Input(output.getBuffer(), 0, output.total());
    Object thawed = kryo.readClassAndObject(input);

    System.out.println(thawed.equals(order));  // prints: true

MessagePack serialization (with the grains-msgpack library):

    MessagePack msgpack = MessagePackTools.newGrainsMessagePack();

    byte[] data = msgpack.write(order);
    OrderGrain unpacked = msgpack.read(data, OrderGrain.class);

    System.out.println(unpacked.equals(order));  // prints: true

Native support for Java serialization:

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    new ObjectOutputStream(out).writeObject(order);

    ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
    Object read = new ObjectInputStream(in).readObject();

    System.out.println(read.equals(order));  // prints: true

Setup

The Grains framework (published on Maven Central) requires Java 7 or greater, and Maven 2.2.1 or greater.

  1. Create a new package to contain your object model, for example: com.acme.model

  2. Configure your POM to pre-compile this package during the generate-sources phase:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
            <source>1.7</source>
            <target>1.7</target>
        </configuration>
        <executions>
            <execution>
                <phase>generate-sources</phase>
                <goals><goal>compile</goal></goals>
                <configuration>
                    <includes>
                        <include>com/acme/model/**</include>
                    </includes>
                </configuration>
            </execution>
        </executions>
    </plugin>
  3. Configure the grains-plugin to run during the generate-sources phase:

    <plugin>
        <groupId>net.nullschool</groupId>
        <artifactId>grains-plugin</artifactId>
        <version>0.8.0</version>
        <executions>
            <execution>
                <phase>generate-sources</phase>
                <goals><goal>generate</goal></goals>
            </execution>
        </executions>
    </plugin>
  4. Add a dependency on grains-core:

    <dependency>
        <groupId>net.nullschool</groupId>
        <artifactId>grains-core</artifactId>
        <version>0.8.0</version>
    </dependency>
  5. (optional) Add a dependency on the serialization library of your choice, such as:

    <dependency>
        <groupId>net.nullschool</groupId>
        <artifactId>grains-jackson</artifactId>
        <version>0.8.0</version>
    </dependency>

Done! Any interface in com.acme.model annotated with @GrainSchema will have a grain implementation generated when mvn compile is invoked. By default, all generated sources appear in the target/generated-sources/grains/com/acme/model directory.

See the wiki for more details.

Acknowledgements

Clojure's defrecord macro provided the main inspiration for grains.

Grains uses Semantic Versioning

About

The "Grains" Java framework generates thread-safe, versionable objects.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages