I have a JAVA Class that is defied as a managed-bean. The code below is a stripped down version of it:
package ca.wfsystems.core;
import lotus.domino.*;
public class Utils {
public static void recycleObjects(Object... args) {
for (Object o : args) {
if (o != null) {
if (o instanceof Base) {
try {
((Base) o).recycle();
} catch (Throwable t) {
// who cares?
}
}
}
}
} //end recycleObjects
public static void sysOut(Object msg){
System.out.println(msg.toString());
} //end sysOut
}// End Class
The call to recycleObjects(someObject) works fine when called from JAVA Code, but when I call it from SSJS in a button on an XPage called TestError I get the message "State data not available for /TestError because no control tree was found in the cache."
The SSJS code in the button is:
WFSUtils().sysOut("In Button");
var vw:NotesView = WFSAppProperties().get(sessionScope.get("ssApplication")).getAppDB().getView("vwWFSForms");
WFSUtils().sysOut("Testing Bean" + vw.getName());
WFSUtils().recycleObjects(vw);
where WFSUtils is the name of the managed bean.
the error in the client says:
Error while executing JavaScript action expression
Script interpreter error, line=6, col=12: Java method 'recycleObjects(lotus.domino.local.View)' on java class 'ca.wfsystems.core.Utils' not found
JavaScript code
I have searched for the error "State data not available for" but found a single reference aout it when using the Extension Library but this code does not use it.
You are using varargs in your method.
It's not possible to use varargs from SSJS. Instead, you might call the same method as:
WFSUtils().recycleObjects([vw]);
It will work in that way.
Related
I am trying to use the JMXWrapper class/project
For a current project for a set of JMX classes all of them work in peace on either JConsole or VisualVM
For one of them I tried to adapt or work with JMXWrapper:
public interface MainJmxMBean {
boolean showIfMainIsRunning();
void stopMain();
}
and
#JMXBean(description="Administrates the Main app", sorted=true)
class MainJmx implements MainJmxMBean {
private boolean isMainRunning;
MainJmx() {
isMainRunning =true;
}
#Override
#JMXBeanOperation(name="Show If Main Is Running",
description="Shows if the Main app is running or not",
sortValue="1")
public boolean showIfMainIsRunning() {
return isMainRunning;
}
#Override
#JMXBeanOperation(description="Stops the Main app", sortValue="2")
public void stopMain() {
isMainRunning = false;
}
}
Note: The class shown above works fine without the annotations. Now was annotated to improve the information and its use in JConsole/VisualVM
And finally
private void registerMBeanWithJMXBeanWrapper(ObjectJmxMBean objectJmxMBean) {
try {
//System.out.printf("%s %n", objectJmxMBean.toString());
ObjectName objectName = new ObjectName(objectJmxMBean.getName());
server.registerMBean(new JMXBeanWrapper(objectJmxMBean.getObject()), objectName);
}
catch(MalformedObjectNameException |
InstanceAlreadyExistsException |
MBeanRegistrationException |
NotCompliantMBeanException |
IntrospectionException e) {
System.err.printf("[CanonicalName] %s - ERROR: %s %n", e.getClass().getCanonicalName(), e.getMessage());
}
}
The important part of above is: new JMXBeanWrapper(objectJmxMBean.getObject())
Until here I did do all the instructions according with the JMXBeanWrapper documentation shared in the link in the top of this post and even from the author's post:
Adding descriptions to JMX beans using an annotation wrapper
When I run the Main app, through either JConsole or VisualVM I can see the annotations being applied and working how is expected, therefore until here the goal seems been accomplished.
Problem: the problem is when I do click to either of them arises:
The complete error message is:
Problem invoking stopMain:
java.lang.IllegalAccessException
Class com.udojava.jmx.wrapper.JMXBeanWrapper can not access a member of class
com.manuel.jordan.jmx.admin.MainJmx with modifiers "public"
Observation: seems the error is thrown directly by JConsole or VisualVM, because according with the JMXBeanWrapper.java source code, there is no the throw new IllegalAccessException statement with the part of that message with modifiers "public"
Note & Observation: according with the project shared on Github, it was tested with JDK 6 and I am using/working with JDK 8.
What could be wrong or missing in the configuration?
The solution is the following:
Edit from:
#JMXBean(description="Administrates the Main app", sorted=true)
class MainJmx implements MainJmxMBean {
private boolean isMainRunning;
MainJmx() {
isMainRunning =true;
}
To
#JMXBean(description="Administrates the Main app", sorted=true)
public class MainJmx implements MainJmxMBean {
private boolean isMainRunning;
MainJmx() {
isMainRunning =true;
}
Conclusion: the JMXWrapper needs that the class annotated with #JMXBean must be public.
How you can see the constructor can remain being package default
I am trying to create a client library that reads JSON from an external file online. I already know about the function interfaces and optionals, but I was wondering if there is a way to allow users to supply callback functions such that the parent function exits completely. For JavaScript, such a function is as follows:
file.read('hello', function(err, data) {
// something here
});
Basically, I wish to do the same in Java. How can I do this such that the error callback supersedes the read function? What I mean is that in the event that the error callback is called, then read should not return a value at all. If the callback is not called then the read should return the value.
You could have the user pass in a function and then just not do anything with it if there is no error.
This example assumes that you have a custom class called Error that the caller is aware of and would like to interact with in case of an error.
public void read (String str, Function<Error,Void> errorFunc)
{
//interact w/ libraries, boolean error = true or false
//if there is an error, variable err of type Error contains information
if (error)
{
errorFunc.apply(err);
}
}
In Java upto 1.7 the only way to achieve javascript like callbacks is thru interface. The api user who calls your method read has the liberty of implementing what he feels needs to be done to handle the error by writing an implementation class for the interface at the invocation point.
public String read(String options,IErrorCallBack errorHandler) throws Exception {
try {
// When everything works fine return what you think should be returned.
return "Success";
}
catch(Exception e) {
// On Error call the function on the error handler.
errorHandler.doSomething();
throw e;
}
}
public interface IErrorCallBack {
public void doSomething();
}
// The invocation point.
read("myString", new IErrorCallBack() {
public void doSomething() {
// Your implementation.
}
});
in my application the follwoing code is used. Can some one give a detailed explanation for the code that is highlighted?
I understood that in first highlighted block java reflection is used in invoking the method handle_validation..but need the detailed explanation.
Then in second highlighted block RemoteException is thrown..
My exact question is why they used reflection to call EngineHandlerIF and then why they are using RMI in this EngineHandlerIF to invoke the definition of method in EngineHandler?
private static EngineHandlerIF init() {
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] { "validation.xml" });
String[] beans = ctx.getBeanDefinitionNames();
for (String string : beans) {
logger.info(string);
}
EngineHandlerIF engine = (EngineHandlerIF) ctx.getBean("engine");
return engine;
}
private Object callEngineMethod(MiddlewareMessage mmsg) {
Object resultObj;
try {
**String methodName = "handle_validation";
Method method = EngineHandlerIF.class.getDeclaredMethod(methodName, MiddlewareMessage.class);
method.setAccessible(true);
resultObj = method.invoke(engine, new Object[] { mmsg });**
} catch (Exception e) {
logger.error("sendMessage Exception: ", e);
return new Boolean(false);
}
return resultObj;
}
EngineHandlerIF:
----------------
**public abstract String handle_validation(MiddlewareMessage mmsg) throws RemoteException;**
EngineHandler:
--------------
public String handle_validation(MiddlewareMessage mmsg) throws Exception {
//some code
}
I understood that in first highlighted block java reflection is used
in invoking the method handle_validation..but need the detailed
explanation.
That's pretty much it. The only other bit is the
method.setAccessible(true);
which makes the method accessible to the caller (e.g. from private to public), thus allowing you to call it. However the above method does appear to be public already. Perhaps this is some legacy following a refactor ?
Note that this isn't RMI (remote method invocation), but rather reflection. The only RMI I can see here is the handle_validation() method possibly throwing a RemoteException.
Maybe someone had just discovered the hammer of a reflection so everything, including method that were already public, started looking like a nut.
It is garbage: throw it away. Just call the method directly.
How can I call a function when a specific event occurs in my java Applet ?
In my Javascript I has the following code, that always return a empty value.
$(function () {
alert(document.applets[0].returnClientId());
});
I need to call this alert, just when a specific method is executed. To be more specific, the method called identify, that exists in my java Applet.
The identify method, exists in my Util.class, that don't extends from JApplet.
My FormMain.class extends from JApplet and I call some methods (including the identify method) from this Util.class.
UPDATE: My Java Code
public String getClientid() {
return clientid;
}
public void setClientid(String clientid) {
this.clientid = clientid;
}
public String returnClientId() {
return getClientid();
}
public void identify() {
try {
fingerprintSDK.prepareForIdentification(this.template);
ResultSet rs = identifyStmt.executeQuery();
while (rs.next()) {
byte[] templateBuffer = rs.getBytes("template");
Template referenceTemplate = new Template(templateBuffer);
boolean matched = fingerprintSDK.identify(referenceTemplate);
if (matched) {
// ui is my FormMain instance
ui.showImage(GrFingerJava.getBiometricImage(template,
fingerprint, fingerprintSDK));
ui.writeLog("Found. Client = "
+ rs.getString("Name"));
ui.setClienteid(rs.getString("Cliente_Id"));
ui.disableTemplate();
return;
}
}
ui.writeLog("Not Found.");
ui.enableTemplate();
} catch (SQLException e) {
ui.writeLog(e.getMessage());
} catch (GrFingerJavaException e) {
ui.writeLog(e.getMessage());
}
}
The Identify method is executed just when my User put the finger in the biometric device.
Someone has some idea ?
Suppose you have the following JS function
function foo(client) {
alert(client);
}
you'll modify your Utils.java as follows
public void identify() {
// the rest of your code
String id = rs.getString("Cliente_Id");
ui.setClienteid(id);
// call the Javascript function
JSObject.getWindow(ui).eval(String.format("foo(%s)", id));
}
Invoking Javascript code from an Applet
Java to Javascript communication (Official Oracle docs)
To compile the code using netscape.javascript.* package you need the $JAVA_HOME/jre/lib/plugin.jar. See here
In order to call JavaScript, Java code uses the
netscape.javascript.JSObject and netscape.javascript.JSException
classes. Since the release of Java 2, Standard Edition version 1.4,
these classes are provided in the jar file jre/lib/plugin.jar within
either the Java Development Kit or Java Runtime Environment. If you
reference these JavaScript classes, you will need to add plugin.jar to
your compilation classpath. This can be done through your Java IDE, if
you use one, or by passing the -classpath command-line argument to the
Java compiler javac.
At run-time, the Java Plug-In automatically makes these classes
available to applets, so no changes to the applet or how it is set up
are necessary.
Using the JDK 6 ScriptEngine mechanism, anything that goes wrong during an "eval" or "invokeMethod" or whatever results in a ScriptException being thrown back to the invoking Java environment. As far as I've been able to tell by experimentation and source code reading, the best I can do to get information back from Javascript when my Javascript code wants to throw an exception is to throw a string. That string shows up in the "getMessage" return value from the ScriptException object. Not pretty.
It seems like it would be nice to be able to:
if (somethingWrong) {
throw { error: Errors.INVALID_SOMETHING, context: whatever() };
}
from Javascript, and then the Java code could somehow get at that object. I fear however that given the current implementation of the Rhino ScriptEngine wrapper, that's just not possible. If anybody knows a trick that does work, however, I'd love to see it.
Rhino does have poor support for Exceptions, they arent as usable as or helpful as they are in other Scripting engines like Groovy or JRuby.
To help you debug problems, I think you can use this trick. Rhino adds a non standard property to the Error object which you can access to print out some information about the Error.
try {
someCode()
}
catch(e) {
if(e.rhinoException != null)
{
e.rhinoException.printStackTrace();
}
}
You could also use Bindings to indicate that something went wrong?
I understand what you are looking for now. Its not pretty, in fact its terrible, but you can get access to the underlying JavaScriptException and then get hold of the value where you threw the Exception.
package test;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import sun.org.mozilla.javascript.*;
public class Main {
private static ScriptEngineManager mgr = new ScriptEngineManager();
private static ScriptEngine engine = mgr.getEngineByName("JavaScript");
public static void main(String... args) {
System.out.println("START");
try {
engine.eval("throw { error: \"cheese\", context: \"payload\" };");
} catch (ScriptException e) {
JavaScriptException jse = (JavaScriptException)e.getCause();
Object obj = jse.getValue();
ScriptableObject so = (ScriptableObject)obj;
System.out.println(so.get("error", so));
System.out.println(so.get("context", so));
}
System.out.println("END");
}
}
You could serialize your error object as a JSON string and then deserialize in Java.
FWIW, I think it would also be hugely useful if you could throw a Java exception object and have that propagate up the stack. For instance, to adapt the code from above:
try {
engine.eval("throw new java.lang.IllegalArgumentException( 'no cookie!' )" );
}
catch (ScriptException e) {
Throwable cause = e.getCause();
if ( cause != null && cause instanceof IllegalArgumentException ) {
// ...react explicitly
}
else {
// ...react generically
}