1

I want to put global property named "entities" in JS scope. Entity is basically Java class describing Person.

public class EntityJS extends ScriptableObject {
    private String firstName;
    private String lastName;
    private Double salary;
    private String email;

    @Override
    public String getClassName() {
        return "Entity";
    }

    public EntityJS() {
    }

    public EntityJS(String firstName, String lastName, Double salary, String email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.salary = salary;
        this.email = email;
    }

    public void jsConstructor() {
        this.firstName = "";
        this.lastName = "";
        this.salary = 0.;
        this.email = "";
    }

    public void jsSet_salary(Double value) {
        this.salary = value;
    }

    public Double jsGet_salary() {
        return this.salary;
    }

    public void jsSet_firstName(String value) {
        this.firstName = value;
    }
    //the rest of getters & setters
}

Entity class is almost the same class like EntityJS, except it extends only java Object.

I want to allow javascript user modify global variable "entities". After executing user's script, I want to retrieve this object back to Java (and perform some operations later on).

I've commented interesting lines with results and expected returned values. Here is my code of trying to execute user's code:

public String execute(String code, ObservableList<Entity> entities) {
    Context context = Context.enter();
    try {
        Scriptable scope = context.initStandardObjects();

        ScriptableObject.defineClass(scope, EntityJS.class, true, true);

        EntityJS[] objects = new EntityJS[entities.size()];
        for(int i = 0; i < entities.size(); ++i){
            objects[i] = new EntityJS(entities.get(i).getFirstName(), entities.get(i).getLastName(), entities.get(i).getSalary(), entities.get(i).getEmail());
        }

        ScriptableObject.putProperty(scope, "e1", Context.javaToJS(objects, scope));
        // typing "e1" (which is equal to "code" value) returns "[Lentity.EntityJS;@7959b389"

        Object[] array = entities.toArray();
        ScriptableObject.putProperty(scope, "e2", array);
        // same for e1

        Object wrappedOut = Context.javaToJS(entities, scope);
        ScriptableObject.putProperty(scope, "e3", wrappedOut);
        //this works quite nice, but it doesn't behave like JS object
        //it returns, good-looking array:
        //[Entity{firstName='Alwafaa', lastName='Abacki', salary=1000.0, email='zdzisiek@adad.com'},
        //Entity{firstName='chero', lastName='Cabacki', salary=2000.0, email='bfadaw@dadaad.com'}]
        //Unfortunately, if I want to get e.g. salary value I have to call
        //e.get(0).getSalary() which returns string :(
        //if I want to add number I have to call
        //Number(e.get(0).getSalary()) to get Number

        ScriptableObject.putProperty(scope, "e4", Context.javaToJS(objects[0], scope));
        //this results in "TypeError: Cannot find default value for object."

        Object result = context.evaluateString(scope, code, "<cmd>", 1, null);
        return context.toString(result);
    } catch (Exception ex) {
        System.out.println(ex.getMessage());
        return ex.getMessage();
    } finally {
        Context.exit();
    }
}

I want to give user "entities" JS-like array, which could be modified e.g. this way:

    entities.forEach(function(entity){entity.salary += 1000;})

I'd like salary property to be Number, of course. Does someone know how can I approach this? Thanks in advance

Szymek
  • 69
  • 9

2 Answers2

2

You can transfer Java Objects into JSON String on the server side and pass it to the client - javascript. When the client receives response from the server (JSON String containing your ojects), you can parse json.

You can convert Java Objects into JSON (on the server side), check this tutorials:

GSON https://www.mkyong.com/java/how-do-convert-java-object-to-from-json-format-gson-api/

Jackson https://www.mkyong.com/java/jackson-2-convert-java-object-to-from-json/

This is how to parse JSON object in js. https://www.w3schools.com/js/js_json_parse.asp

I want to allow javascript user modify global variable "entities". After executing user's script, I want to retrieve this object back to Java (and perform some operations later on).

You can make an AJAX request to the server passing modified objects. Again, on the js side you convert these objects into JSON, then pass them to the server, and parse JSON String into a collection (array) of your objects.

This is how to convert javascript objects into JSON String Convert JS object to JSON string

I have Java Application, which uses Rhino (as in tags). I have TextArea, where user types JS code. I need to give user the entities object.

So, pass the text entered by the user into your server, parse it. Make sure that you are passing valid JSON though.

Yan Khonski
  • 12,225
  • 15
  • 76
  • 114
1

Depends on your JS version, you can do the following:

ES5

function Person(firstName, lastName, salary, email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.salary = salary;
        this.email = email;
    }

var john = new Person("john", "smith", 500, "john.smith@john.com");
var jane = new Person("jane", "doe", 650, "jane.doe@jane.net");
var people = [john, jane];

//mutating the original values
people.forEach(function(person) {person.salary += 500})

ES6

class Person {
  constructor(firstName, lastName, salary, email) {
    this.firstName = firstName;
        this.lastName = lastName;
        this.salary = salary;
        this.email = email;
  }
}

let john = new Person("john", "smith", 500, "john.smith@john.com");
let jane = new Person("jane", "doe", 650, "jane.doe@jane.net");
let people = [john, jane];

people.forEach(person => person.salary += 500);
silicakes
  • 6,364
  • 3
  • 28
  • 39
  • You must have mistunderstand the problem. I dont want to define all the constructors in JS. I want to map JAVA object consisting of Entities into JavaScript, where I can modyfy them. – Szymek Jun 15 '17 at 13:47
  • You have the data in JAVA - and you wish to pass it to the browser? Why not use something like https://github.com/google/gson ? The browser works great with JSON as it's just a plain JS object. – silicakes Jun 15 '17 at 13:50
  • I have Java Application, which uses Rhino (as in tags). I have TextArea, where user types JS code. I need to give user the `entities` object. – Szymek Jun 15 '17 at 14:03