Skip to content

A java framework using typed JSON for looseless communication of composed objects by one generic endpoint. Functionality is provided by special call objects with a generic execute method. Predefined generic calls for files, JSON, Excel, CSV, databases or templates. Compared with todays RPC its a "Remote Object Call" (ROC) architecture.

License

fluentcodes/elasticobjects

Repository files navigation

Open Source Helpers

elasticobjects.org provide a detailed documentation with interactive examples build by template calls. The sources you find in example-springboot.

(EO) Elastic Objects

Elastic Objects is a tiny layer offering path access methods to any java object tree.

The access to underlying java objects is mediated by key and strict object configurations defined by  ModelConfig.json and  FieldConfig.json in the class path. The configurations become first class citizen to determine type in an object tree.

Embedded  Call objects could manipulate the object tree with a generic execute method. It's a "Remote Object Call" (ROC) architecture instead of RPC concepts.

With the configuration key embedded in json the serialization/deserialization allows typesafe communication between computers without endpoints or web frameworks. Embedded in arbitrary text it could initiate complex workflows or compose complex text.

Core (elastic-objects)

elastic-objects Module

The core has actually no dependencies beside Log4j and is rather small with a jar size of approximately 90 KB.

<dependency>
    <groupId>org.fluentcodes.projects.elasticobjects</groupId>
    <artifactId>elastic-objects</artifactId>
    <version>0.9.4</version>
</dependency>

elastic-objects Examples

The following examples you find in  EOReadmeTest as runnable tests. The test object is  AnObject.

Get and Set

Some get and set operations.

EoRoot root = EoRoot.ofValue(CONFIG_MAPS, new AnObject());
EOInterfaceScalar child = root.set("test", "myAnObject", "myString");

assertEquals("test", root.get("myAnObject", "myString"));
assertEquals("test", child.get());

Underlying Object

The set method changes the value of  AnObject via its ≡AnObject configuration :

EoRoot root = EoRoot.ofValue(CONFIG_MAPS, new AnObject());
root.set("test", "myAnObject", "myString");

AnObject anObject = (AnObject) root.get();
assertEquals("test", anObject.getMyAnObject().getMyString());    

String Path Representation

For all accessors one can use a path string with a "/" delimiter like in a file system. Again we set the value test in the fields ≡AnObject and ≡myString.

EoRoot root = EoRoot.ofValue(CONFIG_MAPS, new AnObject());
EOInterfaceScalar child = root.set("test", "myAnObject/myString");

assertEquals("test", root.get("myAnObject/myString"));
assertEquals("test", child.get());

Remove child

One can remove a branch from the object tree in a path way.

EoRoot root = EoRoot.ofValue(CONFIG_MAPS, new AnObject());
EOInterfaceScalar child = root.set("test", "myAnObject/myString");

EO parent = child.remove();
assertFalse(parent.hasEo("myString"));

AnObject parentObject = (AnObject) parent.get();
assertNull(parentObject.getMyString());    

Field Length Restrictions

The field configuration ≡myString has a max size of 20. It will be checked when setting a value. In this example the value test01234567890123456789 has the length 24 and produce an exception.

EoRoot root = EoRoot.ofClass(CONFIG_MAPS, AnObject.class);
assertEquals(AnObject.class, root.getModelClass());
Assertions.assertThatThrownBy(
        ()->{root.set("test01234567890123456789", "myString");})
        .isInstanceOf(EoException.class)
        .hasMessageContaining("Problem creating child at '/' with key 'myString' with value 'test01234567890123456789' with message String value for field 'test01234567890123456789' has size 24 bigger than max length 20.");

Interactive example: https://www.elasticobjects.org/examples/AnObjectTooLong.html.

Restrictions to a Map

It's possible to add field configurations with a Map as underlying object. In  ModelConfig.json the configuration of ≡AnObjectMap has the field definition ≡myString. This will be checked within  ModelConfigMap

.

Here the previous example with "AnObjectMap":

EoRoot root = EoRoot.ofClassName(CONFIG_MAPS, "AnObjectMap");
assertEquals(LinkedHashMap.class.getSimpleName(), root.get().getClass().getSimpleName());
Assertions.assertThatThrownBy(
        ()->{root.set("test01234567890123456789", "myString");})
        .isInstanceOf(EoException.class)
            .hasMessageContaining("Problem creating child at '/' with key 'myString' with value 'test01234567890123456789' with message String value for field 'test01234567890123456789' has size 24 bigger than max length 20.");

Interactive example: https://www.elasticobjects.org/examples/AnObjectMapTooLong.html.

Field does not exist

When field definition are set, also names will be checked:

EoRoot root = EoRoot.ofClassName(CONFIG_MAPS, "AnObjectMap");
Assertions.assertThatThrownBy(
        ()->{root.set("test", "notValid");})
        .isInstanceOf(EoException.class)
        .hasMessageContaining("Problem creating child at '/' with key 'notValid' with value 'test' with message No field defined for 'notValid'.");

Interactive example: https://www.elasticobjects.org/examples/AnObjectMapFieldNotExists.html.

Typed JSON

The default json representation contains keys of the model configuration ≡AnObject:

    EoRoot root = EoRoot.ofValue(CONFIG_MAPS, new AnObject());
    EOInterfaceScalar child = root.set("test", "myAnObject", "myString");
    assertEquals("{\n" +
            "  \"_rootmodel\": \"AnObject\",\n" +
            "  \"(AnObject)myAnObject\": {\n" +
            "    \"myString\": \"test\"\n" +
            "  }\n" +
            "}", root.toJson());

From JSON

This typed json will mapped to the appropriate object class when deserialized:

    EoRoot root = EoRoot.ofValue(CONFIG_MAPS, new AnObject());
    root.set("test", "myAnObject", "myString");
    String json = root.toJson();      
     
    EoRoot rootFromJson = EoRoot.ofValue(CONFIG_MAPS, json);       
    assertEquals(AnObject.class, rootFromJson.get().getClass());
    
    AnObject myAnObject = (AnObject)rootFromJson.get();
    assertEquals("test", myAnObject.getMyAnObject().getMyString());

Interactive example: https://www.elasticobjects.org/examples/AnObjectTyped.html.

Clone

When a java object is mapped to EO the underlying object is a clone with the same structure and leaf values.

final AnObject anObject = new AnObject();
anObject.setMyString("value1");

final EoRoot rootMap = EoRoot.ofValue(CONFIG_MAPS, anObject);
final AnObject cloned = (AnObject) rootMap.get();

assertNotEquals(anObject, cloned);
assertEquals(anObject.getMyString(), cloned.getMyString());

Transform

One can easily transform an object to another type, when the target object has the same fields. The following example
creates a Map from AnObject:

final AnObject anObject = new AnObject();
anObject.setMyString("value2");

final EoRoot rootMap = EoRoot.ofClass(CONFIG_MAPS, anObject, Map.class);
final Map transformed = (Map) rootMap.get();

assertEquals(anObject.getMyString(), transformed.get("myString"));

Non Mapped values

Every field key starting with underscore will not be mapped to the parent object.

final String json = "{\"myString\":\"test\", \"_comment\":\"FieldNames with underscore will not set in parent object.\"}";

final EoRoot root = EoRoot.ofClass(CONFIG_MAPS, json, AnObject.class);

assertEquals("FieldNames with underscore will not set in parent object.", root.get("_comment"));
assertEquals("{\n" +
        "  \"myString\": \"test\"\n" +
        "}", root.toJson(JSONSerializationType.STANDARD));

Interactive example: https://www.elasticobjects.org/examples/Comment.html.

Calls (eo-calls)

eo-calls Module

The calls module with a jar size of about 150 KB offers some basic calls also using configurations with a role permission concept for files and directories simple csv or templates.

<dependency>
    <groupId>org.fluentcodes.projects.elasticobjects</groupId>
    <artifactId>eo-calls</artifactId>
    <version>0.9.2</version>
</dependency>

eo-calls Examples

The call classes implementing the  Call interface offer functionality. A bunch of calls including file access or templates you find in  eo-calls.

The following examples using  SinusValueCall are found in  EOReadmeTest.

Java Example

The generic execute method has EO as input. Here we set the field key "squareDegree" to 2.1 and directly call  SinusValueCall.

    final Call call = new SinusValueCall();
    EoRoot root = EoRoot.ofValue(CONFIG_MAPS, new HashMap());
    EOInterfaceScalar child = root.set(2.1, "squareDegree");
    assertEquals(2.1, child.get());

    assertEquals(Double.valueOf(0.8632093666488737), call.execute(child));

JSON Example

This call could be also embedded in some arbitrary json using the ≡sourcePath as input. The result will stored to the ≡targetPath "sinusValue".

    EoRoot root = EoRoot.ofValue(CONFIG_MAPS, "{\n" +
            "  \"(Double)squareDegree\":1,\n" +
            "  \"(SinusValueCall)sinusValue\": {\n" +
            "    \"sourcePath\": \"/squareDegree\"\n" +
            "  }\n" +
            "}");
    root.execute();
    assertEquals("{\n" +
            "  \"squareDegree\": 1.0,\n" +
            "  \"sinusValue\": 0.8414709848078965\n" +
            "}", root.toJson(JSONSerializationType.STANDARD));

Interactive example: https://www.elasticobjects.org/examples/SinusValueCall.html.

Template Example

This json will be interpreted in an arbitrary text file via template call with the "@{...}" pattern. Here the target _asString will return the result to the template instead of setting the target in json.

    EoRoot root = EoRoot.of(CONFIG_MAPS);
    String template = "START - @{\n" +
            "  \"(Double)source\":1,\n" +
            "  \"(SinusValueCall)_asString\": {\n" +
            "    \"sourcePath\": \"/source\"\n" +
            "  }\n" +
            "}. - END";
    Call call = new TemplateCall(template);
    assertEquals("START -0.8414709848078965 - END", call.execute(root));

Interactive example: https://www.elasticobjects.org/examples/SinusValueCallTemplate.html.

Other Template forms

Calls could be included in an attribute and command form. This will be demonstrated by the following examples:

Files

http://localhost:8080/examples/FileCall.html http://localhost:8080/examples/JsonCall.html

Templates

Interactive Examples: http://localhost:8080/examples/TemplateExamples.html

Csv (eo-csv)

eo-csv offers calls and configurations for reading and writing csv files using OpenCsv.

<dependency>
    <groupId>org.fluentcodes.projects.elasticobjects</groupId>
    <artifactId>eo-csv</artifactId>
    <version>0.9.4</version>
</dependency>

Interactive examples: http://localhost:8080/examples/ListCall.html

Database (eo-db)

eo-db is experimental providing the execution of sql configurations as list or as query.

<dependency>
    <groupId>org.fluentcodes.projects.elasticobjects</groupId>
    <artifactId>eo-db</artifactId>
    <version>0.9.4</version>
</dependency>

Interactive examples: https://www.elasticobjects.org/examples/DbCall.html.

Excel (eo-xlsx)

eo-xlsx offers calls and configurations for reading and writing xlsx files using Apache POI.

<dependency>
    <groupId>org.fluentcodes.projects.elasticobjects</groupId>
    <artifactId>eo-xlsx</artifactId>
    <version>0.9.4</version>
</dependency>

Interactive examples: http://localhost:8080/examples/ExcelCall.html

Other Modules

elastic-objects-test

elastic-objects-test provide tests for the elastic-objects module. The main package providing test helper and test objects to other modules.

Since it has just test purposes there is actual no package on mvn central.

examples-springboot

examples-springboot are the sources for the spring boot web example on http://www.elasticobjects.org.

Since it has just demo purposes there is actual no package on mvn central.

Background

Elastic Objects

Elastic Objects is a generic object wrapper skin with typed path methods to an java object skeleton. Typed objects are embedded in an untyped map structure.

Some code examples you will find in http://elasticobjects.org/eo/EO.html.

Model Configurations

For the access to the embedded java objects EO is provided by preloaded model configurations in JSON.

Call Types

A special Call bean with a generic execution method offers functionality. Its has the following important fields:

Conclusion

The project has now version 0.9.4.

As a tool for creating and manipulating java objects it offers a lot of benefits.

For productive use in a flexible microservice architecture it's good enough for a proof of concept.

Links

About

A java framework using typed JSON for looseless communication of composed objects by one generic endpoint. Functionality is provided by special call objects with a generic execute method. Predefined generic calls for files, JSON, Excel, CSV, databases or templates. Compared with todays RPC its a "Remote Object Call" (ROC) architecture.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published