I'm learning GWT and currently I'm struggeling with RPC. I have a simple Project: a Label, a Textbox, an outputLabel and a Button.
I want when the user enters his Name in the TextBox and press the "send" Button he will get a Message from the Server "Hello "+name+"Here speaks the Server" - stupid example.
However in my CLient I have a package GUI and a Package Service and my entrypoint class
public class TestGwt270 implements EntryPoint {
public void onModuleLoad()
{
TestGwt270ClientImpl clientImpls = new TestGwt270ClientImpl("/TestGwt270/testgwt270service");
GWT.log("Main "+GWT.getModuleBaseURL() );
RootPanel.get().add(clientImpls.getMainGUI());
}
MyGui:
public class MainGUI extends Composite
{
private TestGwt270ClientImpl serviceImpl;
private VerticalPanel vPanel;
private TextBox inputTB;
private Label outputLbl;
public MainGUI(TestGwt270ClientImpl serviceImpl)
{
this.vPanel = new VerticalPanel();
initWidget(vPanel);
this.inputTB = new TextBox();
this.inputTB.setText("Gib deinen Namen ein");
this.outputLbl = new Label("Hier kommt der output");
this.vPanel.add(this.inputTB);
this.vPanel.add(this.outputLbl);
Button sendBtn = new Button("send");
sendBtn.addClickHandler(new MyClickhandler());
this.vPanel.add(sendBtn);
}
public void updateOutputLbl(String output)
{
this.outputLbl.setText(output);
}
private class MyClickhandler implements ClickHandler
{
#Override
public void onClick(ClickEvent event) {
// TODO Auto-generated method stub
serviceImpl.sayHello(inputTB.getText());
}
}
}
TheService:
#RemoteServiceRelativePath("testgwt270service")
public interface TestGwt270Service extends RemoteService
{
String sayHello(String name);
}
AsyncService:
public interface TestGwt270ServiceAsync
{
void sayHello(String name, AsyncCallback<String> callback);
}
ClientInterface:
public interface TestGwt270ServiceClientInt
{
void sayHello(String name);
}
Client Implementation:
public class TestGwt270ClientImpl implements TestGwt270ServiceClientInt
{
private TestGwt270ServiceAsync service;
private MainGUI maingui;
public TestGwt270ClientImpl(String url)
{
GWT.log(url);
// TODO Auto-generated constructor stub
this.service = GWT.create(TestGwt270Service.class);
ServiceDefTarget endpoint = (ServiceDefTarget) this.service;
endpoint.setServiceEntryPoint(url);
this.maingui = new MainGUI(this);
}
public MainGUI getMainGUI()
{
return this.maingui;
}
#Override
public void sayHello(String name) {
// TODO Auto-generated method stub
this.service.sayHello(name, new MyCallback());
}
private class MyCallback implements AsyncCallback<String>
{
#Override
public void onFailure(Throwable arg0) {
// TODO Auto-generated method stub
GWT.log("Failure");
maingui.updateOutputLbl("An Error has occured");
}
#Override
public void onSuccess(String arg0) {
// TODO Auto-generated method stub
GWT.log("Success");
maingui.updateOutputLbl(arg0);
}
}
}
ServerSideCode:
public class TestGwt270ServiceImpl extends RemoteServiceServlet implements TestGwt270Service
{
#Override
public String sayHello(String name) {
// TODO Auto-generated method stub
GWT.log("Hello " + name + "\nHier spricht der Server mit dir");
return "Hello " + name + "\nHier spricht der Server mit dir";
}
}
My Problem is, when I press the Button to send my Name to the server I get following Error:
HandlerManager.java:129 Uncaught com.google.gwt.event.shared.UmbrellaException: Exception caught: (TypeError) : Cannot read property 'sayHello_2_g$' of undefined
I don't know where this Error comes from and I hope you can help me.
I found the answer myself - I made a simple mistake:
In the class MyGUI I got this:
public class MainGUI extends Composite
{
private TestGwt270ClientImpl serviceImpl;
...
public MainGUI(TestGwt270ClientImpl serviceImpl)
{
...
I forgot to assign the serviceImpl
the Fix:
public class MainGUI extends Composite
{
private TestGwt270ClientImpl serviceImpl;
...
public MainGUI(TestGwt270ClientImpl serviceImpl)
{
this.serviceImpl = serviceImpl; //this line is the solution to my problem
...
Related
I have made some code inside of the spring boot back-end application which allows me to change a property of a specific object, this property which needs to be changed is the "status" property:
#Entity
public class Pakketje {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private int code;
private String status = "In magazijn";
public Pakketje() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
To change the property of that object, i will need to state the ID of that object (i think) inside of the react frontend application, and then fetch the PUT-method.
I will show you the method to change the property inside of my spring boot back-end application, this method can be found in the 'Service' class. 'bestaandPakketje' means existing pakketje.
#Override
public Pakketje getPakketjeById(int id) {
return pakketjeRepository.findById(id).orElse(null);
}
#Override
public Pakketje statusOnderweg(Pakketje pakketje) {
Pakketje bestaandPakketje = pakketjeRepository.findById(pakketje.getId()).orElse(null);
bestaandPakketje.setStatus(pakketje.getStatus());
return pakketjeRepository.save(bestaandPakketje);
}
}
And here is the controller:
public class PakketjeController {
#SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
#Autowired
private PakketjeService pakketjeService;
#PostMapping("/add")
public String add(#RequestBody Pakketje pakketje) {
pakketjeService.pakketjeOpslaan(pakketje);
return "Pakketje opgeslagen!";
}
#GetMapping("/getAll")
public List<Pakketje> getAllePakketjes(){
return pakketjeService.getAllePakketjes();
}
#GetMapping("/getById/{id}")
public Pakketje findPakketjeById(int id) {
return pakketjeService.getPakketjeById(id);
}
#PutMapping("/updateOnderweg")
public Pakketje statusIsOnderweg(#RequestBody Pakketje pakketje) {
return pakketjeService.statusOnderweg(pakketje);
}
}
Now the next step is verry hard for me. Each 'pakketje' has his own button which can be clicked to change the property (I will upload the picture so please check it). When that button is clicked the property automatically should change from "In magazijn "to "onderweg".
I would appreciate some help!
I would like to have count down timer in my mobile app, I have used ViewModel and LiveData to share the data between different activities and update the UI. I know the ViewModel & LiveData is working as I have a button which saves the data, but when I try the same from the timer I get the following error:
Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call.
I think the "model = new ViewModelProvider(this).get(viewmodelclass.class);" is wrong, but I have tried to delay the timer before calling the ViewModel class so it has time to initialise all the variables. So not sure how to get the reference to the ViewModel class?
Any ideas how to fix this issue would be highly appreciated, as it seems a very simple but going around in circles trying to fix it.
MainActivity class
package com.example.viewmodellivedata_sandpit;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity
{
private Button buttonBack_activity;
public viewmodelclass model;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get a reference to the ViewModel
model = new ViewModelProvider(this).get(viewmodelclass.class);
LiveData<String> shoppingList = model.getshoppinglist();
model.getshoppinglist().observe(this, new Observer<String>(){
#Override
public void onChanged(#Nullable String s)
{
Log.d("Debug", "String has been updated");
}
});
TextView textView_1 = findViewById(R.id.textView1);
buttonBack_activity = (Button) findViewById(R.id.button1);
buttonBack_activity.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view) {
Log.d("Debug", "Button pressed");
model.writedatatest("send text");
}
});
TimerStateMachineClass mActivity= new TimerStateMachineClass();
mActivity.starttimer();
}
}
ViewModel class
package com.example.viewmodellivedata_sandpit;
import android.util.Log;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class viewmodelclass extends ViewModel {
public MutableLiveData<String> shoppingList;
public MutableLiveData<String> getshoppinglist() {
if (shoppingList == null) {
Log.w("Debug", "Inside the get shopping list");
shoppingList = new MutableLiveData<>();
writedatatest("test message");
}
return shoppingList;
}
public void writedatatest(String incomingdata)
{
Log.w("Debug", "Inside the get shopping list 1 -> "+shoppingList.getValue());
shoppingList.postValue(incomingdata);
}
}
Timer class
public class TimerStateMachineClass extends AppCompatActivity {
public Timer myTimer;
public viewmodelclass model;
int coutner;
public void starttimer()
{
Log.w("Debug", "onCreate savedInstanceState");
model = new ViewModelProvider(this).get(viewmodelclass.class);
Log.w("Debug", "Function start timer");
myTimer = new Timer();
coutner = 0;
myTimer.schedule(new TimerTask() {
public void run() {
TimerMethod();
}
}, 0, 1000);
}
public void TimerMethod()
{
Log.w("Debug", "Timer execution");
// LiveData<String> shoppingList = model.getshoppinglist();
coutner++;
model.writedatatest(Integer.toString(coutner));
}
}
The answer was very simple just need to add onCreateView at the bottom of the code
public class MainActivity extends AppCompatActivity
{
private Button buttonBack_activity;
TextView textView_1;
public static viewmodelclass model;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get a reference to the ViewModel
model = new ViewModelProvider(this).get(viewmodelclass.class);
try{
textView_1 = findViewById(R.id.textView1);
buttonBack_activity = (Button) findViewById(R.id.button1);
buttonBack_activity.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view) {
Log.d("Debug", "Button pressed");
model.writedatatest("send text");
}
});
TimerStateMachineClass mActivity= new TimerStateMachineClass();
mActivity.starttimer();
LiveData<String> shoppingList = model.getshoppinglist();
model.getshoppinglist().observe(this, new Observer<String>(){
#Override
public void onChanged(#Nullable String s)
{
textView_1.setText(s);
Log.d("Debug", "String has been updated ->"+s);
}
});
}catch (Exception e)
{
e.printStackTrace();
}
}
#Nullable
#Override
public View onCreateView(#NonNull String name, #NonNull Context context,
#NonNull AttributeSet attrs) {
return super.onCreateView(name, context, attrs);
}
}
I have test code in which I want to read configurations from consul.The application.properties (src/main/resources) enables the consul config. And I have one POJO class name DBConfig (in src/main/java) which gets the configuration from consul. I have autowired the DBConfig in test class and when I'm running the unit test it is giving me nullpointerexception as it is not getting the values from consul.
How to handle the situation. Please help.
#Configuration
#ConfigurationProperties(prefix="db")
#RefreshScope
public class DBConfig {
private String jdbcURL;
private String username;
private String password;
private String driverClass;
...getter setters.
}
Test Class---
#RunWith(MockitoJUnitRunner.class)
#Transactional(propagation=Propagation.REQUIRED,readOnly=false,rollbackFor=Exception.class)
#SpringBootTest(classes={DBConfig.class})
public class TestUserDao extends DBTestCase {
#Autowired
private DBConfig dbConfig;
protected final Resource res = new ClassPathResource("actualDataSet.xml");
#Bean
#Profile("test")
#RefreshScope
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(dbConfig.getDriverClass());
dataSource.setUrl(dbConfig.getJdbcURL());
dataSource.setUsername(dbConfig.getUsername());
dataSource.setPassword(dbConfig.getPassword());
return dataSource;
}
#Bean
#Autowired
public NamedParameterJdbcTemplate jdbcTemplate(DataSource dataSource) {
return new NamedParameterJdbcTemplate(dataSource);
}
#Bean
#Autowired
public UserDAO userDAO(NamedParameterJdbcTemplate jdbcTemplate) {
return new UserDAO(jdbcTemplate);
}
#Override
protected IDataSet getDataSet() throws Exception {
ClassLoader classLoader = getClass().getClassLoader();
String file = classLoader.getResource("actualDataSet.xml").getFile();
return new FlatXmlDataSetBuilder().build(new FileInputStream(file));
}
protected DatabaseOperation getSetUpOperation() throws Exception {
return DatabaseOperation.REFRESH;
}
#Test
public void insertTodo() throws Exception {
}
protected DatabaseOperation getTearDownOperation() throws Exception {
return DatabaseOperation.DELETE;
}
It may be caused by usage of MockitoJUnitRunner class, which will not load ApplicationContext at startup, which means, your beans won't be accessible.
Once you will use SpringRunner class in #RunWith() annotation, Spring should be able to inject DBConfig bean.
I have a bean that implements JSObject ( & Map ) interface as shown below. I have removed some overridden methods to make it easy to read.
package test.nashorn;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import jdk.nashorn.api.scripting.JSObject;
public class JSBean implements JSObject, Map<String,Object>{
/**
* The current values for this object.
*/
private HashMap<String, Object> values = new HashMap<>();
#Override
public String toString() {
System.out.println("ToString");
Set<Entry<String,Object>> entries = values.entrySet();
StringBuilder sb = new StringBuilder();
for(Entry<String,Object> entry:entries){
sb.append(entry.getKey()+ " "+(String)entry.getValue());
}
System.out.println("Completed ToString");
return sb.toString();
}
#Override
public boolean hasMember(String name) {
return has(name);
}
// get the value of that named property
#Override
public Object getMember(String name) {
return get(name);
}
// get the value of that named property
#Override
public void setMember(String name,Object value) {
put(name,value);
}
public Object get(String name) {
System.out.println("JAVA Get is called."+name);
System.out.println("Called for this"+name+" and returned"
+":"+values.get(name));
return values.get(name);
}
#Override
public Object put(String name, Object value) {
System.out.println("JAVA Put is called. Input name: " + name + "\n Input values: " + value);
return values.put(name, value);
}
public boolean has(String name) {
System.out.println("JAVA Has is called. Input name: " + name);
return values.containsKey(name);
}
public JSBean() {
// TODO Auto-generated constructor stub
}
#Override
public Object call(Object arg0, Object... arg1) {
// TODO Auto-generated method stub
return null;
}
#Override
public Object eval(String arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public String getClassName() {
// TODO Auto-generated method stub
return null;
}
#Override
public Object getSlot(int arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public boolean hasSlot(int arg0) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean isArray() {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean isFunction() {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean isInstance(Object arg0) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean isInstanceOf(Object arg0) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean isStrictFunction() {
// TODO Auto-generated method stub
return false;
}
}
When i run the test shown below
#Test
public void testDefaultValMethod(){
JSBean bean = new JSBean();
bean.setMember("hello", " Sport ");
//Add stuff to engine.
engine.put("jsBean", bean);
String source = "(function(){\n"
+ "print(jsBean);"
+ "} )();";
Object obj=null;
try {
obj = engine.eval(source);
} catch (ScriptException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Returned : " + String.valueOf(obj));
}
I see the below error in the console. Ideally Nashorn should have directly called the toString() method of the bean to get the String implementation. Not sure what is going wrong here. I did try adding a call to 'toString()' explicitly in the getMember() method call but that did not fix the problem.
JAVA Put is called. Input name: hello
Input values: Sport
JAVA Get is called.toString
Called for thistoString and returned:null
JAVA Get is called.valueOf
Called for thisvalueOf and returned:null
javax.script.ScriptException: TypeError: cannot.get.default.string in <eval> at line number 2
at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:467)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:451)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:403)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:399)
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
at test.nashorn.NashornTest.testDefaultValMethod(NashornTest.java:386)
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:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: <eval>:2 TypeError: cannot.get.default.string
at jdk.nashorn.internal.runtime.JSType.toPrimitive(JSType.java:514)
at jdk.nashorn.internal.runtime.JSType.toPrimitive(JSType.java:480)
at jdk.nashorn.internal.runtime.JSType.toStringImpl(JSType.java:1391)
at jdk.nashorn.internal.runtime.JSType.toString(JSType.java:589)
at jdk.nashorn.internal.objects.Global.printImpl(Global.java:2782)
at jdk.nashorn.internal.objects.Global.println(Global.java:1497)
at jdk.nashorn.internal.scripts.Script$Recompilation$1$11$\^eval\_.L:1(<eval>:2)
at jdk.nashorn.internal.scripts.Script$\^eval\_.:program(<eval>:1)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:640)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:228)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:446)
... 29 more
Caused by: java.lang.UnsupportedOperationException: cannot.get.default.string
at jdk.nashorn.api.scripting.DefaultValueImpl.getDefaultValue(DefaultValueImpl.java:53)
at jdk.nashorn.api.scripting.AbstractJSObject.getDefaultValue(AbstractJSObject.java:289)
at jdk.nashorn.internal.runtime.JSType.toPrimitive(JSType.java:512)
... 40 more
Returned : null
print or "toString" conversions from scripts call "toString" method on the script object. Any property access (including function valued property) on a JSObject is routed to getMember method. So, to make "valueOf" or "toString" you've to implement appropriate getMember in your JSObject subtype.
Example:
import jdk.nashorn.api.scripting.*;
import javax.script.*;
public class Main {
static class MyJSObject extends AbstractJSObject {
#Override
public Object getMember(String name) {
if (name.equals("toString")) {
// return a "function" object for "toString" property
return new AbstractJSObject() {
#Override
public boolean isFunction() {
return true;
}
#Override
public Object call(Object self, Object...args) {
return self.toString();
}
};
}
return null; // other properties here
}
#Override
public String toString() {
return "my js object";
}
}
public static void main(String[] a) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
e.put("myObj", new MyJSObject());
e.eval("print(myObj)");
}
}
Alternatively, you can also override
Object getDefaultValue(final Class<?> hint) throws UnsupportedOperationException
method in your AbstractJSObject subclass.
import jdk.nashorn.api.scripting.*;
import javax.script.*;
public class Main2 {
static class MyJSObject extends AbstractJSObject {
#Override
public Object getDefaultValue(Class<?> hint) {
if (hint == String.class) {
return toString();
}
throw new UnsupportedOperationException("no conversion for " + hint);
}
#Override
public String toString() {
return "my js object";
}
}
public static void main(String[] a) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
e.put("myObj", new MyJSObject());
e.eval("print(myObj)");
}
}
In Rhino, I have a Scriptable bean like below
/**
*
*/
package test.rhino;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.mozilla.javascript.FunctionObject;
import org.mozilla.javascript.Scriptable;
/**
* #author
*
*/
public class SomeBean implements Scriptable, Map<String,Object> {
/**
* The current values for this object.
*/
private HashMap<String, Object> values = new HashMap<>();
/**
*
*/
public SomeBean() {
System.out.println("SomeBean();");
}
/*
* #see org.mozilla.javascript.Scriptable#getClassName()
*/
#Override
public String getClassName() {
return "SomeBean";
}
/*
* #see org.mozilla.javascript.Scriptable#get(java.lang.String,
* org.mozilla.javascript.Scriptable)
*/
#Override
public Object get(String name, Scriptable start) {
System.out.println("Get is called.");
System.out.println("Called for this" + name + " and returned :" + values.get(name));
return values.get(name);
}
/*
* #see org.mozilla.javascript.Scriptable#put(java.lang.String,
* org.mozilla.javascript.Scriptable, java.lang.Object)
*/
#Override
public void put(String name, Scriptable start, Object value) {
System.out.println("Put is called. Input name: " + name + "\n Input values: " + value);
values.put(name, value);
}
#Override
public Object get(int index, Scriptable start) {
// TODO Auto-generated method stub
return null;
}
#Override
public boolean has(String name, Scriptable start) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean has(int index, Scriptable start) {
// TODO Auto-generated method stub
return false;
}
#Override
public void put(int index, Scriptable start, Object value) {
// TODO Auto-generated method stub
}
#Override
public void delete(String name) {
// TODO Auto-generated method stub
}
#Override
public void delete(int index) {
// TODO Auto-generated method stub
}
#Override
public Scriptable getPrototype() {
// TODO Auto-generated method stub
return null;
}
#Override
public void setPrototype(Scriptable prototype) {
// TODO Auto-generated method stub
}
#Override
public Scriptable getParentScope() {
// TODO Auto-generated method stub
return null;
}
#Override
public void setParentScope(Scriptable parent) {
// TODO Auto-generated method stub
}
#Override
public Object[] getIds() {
// TODO Auto-generated method stub
return null;
}
#Override
public Object getDefaultValue(Class<?> hint) {
// TODO Auto-generated method stub
return null;
}
#Override
public boolean hasInstance(Scriptable instance) {
// TODO Auto-generated method stub
return false;
}
#Override
public int size() {
// TODO Auto-generated method stub
return 0;
}
#Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean containsKey(Object key) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean containsValue(Object value) {
// TODO Auto-generated method stub
return false;
}
#Override
public Object get(Object key) {
System.out.println("MAP -- Get is called.");
// TODO Auto-generated method stub
return values.get(key);
}
#Override
public Object put(String key, Object value) {
values.put(key, value);
System.out.println("MAP -- Put is called.");
// TODO Auto-generated method stub
return value;
}
#Override
public Object remove(Object key) {
// TODO Auto-generated method stub
return null;
}
#Override
public void putAll(Map<? extends String, ? extends Object> m) {
// TODO Auto-generated method stub
}
#Override
public void clear() {
// TODO Auto-generated method stub
}
#Override
public Set<String> keySet() {
// TODO Auto-generated method stub
return null;
}
#Override
public Collection<Object> values() {
// TODO Auto-generated method stub
return null;
}
#Override
public Set<java.util.Map.Entry<String, Object>> entrySet() {
// TODO Auto-generated method stub
return null;
}
private static Scriptable globalPrototype;
public static void finishInit(Scriptable scope, FunctionObject constructor, Scriptable prototype) {
System.out.println("finishInit is called.");
globalPrototype = prototype;
}
}
I can retrieve this bean as a Scriptable object and pass it to the eval() function of a compiled script like below.
String src5 = "(function(){return Name;})();\n";
Script sc = getCompiledScript(src5);
SomeBean sb = new SomeBean();
sb.put("Name", "Matt Murdock");
Scriptable sp = (Scriptable) sb;
result = script.exec(context, sp);
The result print Matt Murdock. We can refer to properties directly here since SomeBean instance is passed as scope to the script execution.
I am unable to find an equivalent way in Nashorn. I can use the source to get a CompiledScript instance but i cannot add SomeBean to the binding without giving it a key and i cannot call its members ( Name ) directly in my JavaScript function. The below code throws error which is obvious since we cannot access the properties without the prefix key.
NSomeOtherBean nsob = new NSomeOtherBean(); // extends AbstractJSObject
nsob.setMember("Name", "Bruce Wayne");
Bindings binding = engine.createBindings();
binding.put("nsob", nsob);
engine.setBindings(binding, ScriptContext.GLOBAL_SCOPE);
result = engine.eval("(function(){return Name;})();\n",binding);
Is there a way in Nashorn to add properties of NSomeOtherBean instance to the scope and access them without using a prefix? like how we can do it in Rhino.
Nashorn equivalent of Rhino Scriptable is jdk.nashorn.api.scripting.JSObject
See javadoc:
https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/JSObject.html
https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/AbstractJSObject.html
Examples:
http://hg.openjdk.java.net/jdk9/dev/nashorn/file/efeb16c75392/samples/jsobj_example.js
http://hg.openjdk.java.net/jdk9/dev/nashorn/file/efeb16c75392/samples/BufferArray.java
http://hg.openjdk.java.net/jdk9/dev/nashorn/file/efeb16c75392/samples/jsobject_mapreduce.js
That said, java.util.Map instances are treated as "special" by Nashorn. i.e., Map keys can be accessed like object properties in Nashorn.