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

55d8306 · Jun 23, 2014
Jun 20, 2013
Jun 20, 2013
Jun 20, 2013
Jun 20, 2013
Jun 18, 2013
Jun 20, 2013
Jun 21, 2013
Jun 18, 2013
Apr 25, 2013
Apr 25, 2013
May 14, 2013
Jun 23, 2014
Jun 20, 2013
Jun 18, 2013

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