Search code examples
javaxpageslotus-noteslotus-domino

How to call a java shared script library from a Java agent in Xpages?


I have an agent that is set to run every day at 8:00
I want to write a java code (in a shared library) and call that library from the agent with parameters.

For Example:

Agent code:

    // ....
    checkAndSendMail(email_1);
    checkAndSendMail(email_2);
    // ....

java library code:

public class Check{       
    public void checkAndSendMail(String email_param){
        // ...
        mail.send(email_param);
        // ...
    }    
}
  • Can I call a java shared script library from a Java agent in Xpages?
  • if yes, then how to call?

Solution

  • You can do this, but this is only possible with a lot of "overhead". Assuming you want to load a Java class in an Agent you could do the following:

    1. Get the design note containing your class (f.e. with a special design view or the Java NAPI)
    2. Export the note with DXL
    3. Extract the content all "$ClassData" fields
    4. Base64 decode the content
    5. Skip the first 42 bytes , and load the resulting byte array with your own class loader (override the findClass method which does a defineClass call)
    6. Now you can instantiate the class in your agent and access it via reflection

    As you can see, it is possible, but for a higher effort than just "doubling" the libraries in the DDE.

    EDIT:

    Here is an example class loader for an agent. The Base64 encoded DXL is already added. The agent instantiates the class ch.hasselba.demo.LoadedClass and calls the method printTime():

    package ch.hasselba.demo;
    
    public class LoadedClass {
    
        public void printTime(){
            System.out.println("Time: " + System.currentTimeMillis() );
        }
    }
    

    The code of the agent (uses lwpd.commons.jar)

    import lotus.domino.AgentBase;
    import com.ibm.commons.util.io.base64.Base64;
    import java.lang.reflect.Method;
    
    public class JavaAgent extends AgentBase {
    
        public void NotesMain() {
    
            try {
                // trucated DXL string
                String dataDXL = "YQAYAAAAAACqAgAAAQAAAAAAAAAAAAAAYAC8AgAAqgKqAgAAAAAAAAAAyv66vgAAADEALwcAAgEAFWNoL2hhc3NlbGJhL3hwYWdlcy9aWgcA";
    
                // base64 decode the string
                String b64 = Base64.decode(dataDXL);
                byte[] b64Bytes = b64.getBytes();
                byte[] classBytes = new byte[b64Bytes.length - 42];
    
                // skip the first 42 bytes
                System.arraycopy( b64Bytes, 42, classBytes, 0, b64Bytes.length - 42);
    
                try {
                    // load the class
                    ByteClassLoader obj = new ByteClassLoader();
                    Class theClass = obj.findClass("ch.hasselba.demo.LoadedClass", classBytes);
                    // instantiate it
                    Object theInstance = theClass.newInstance();
    
                    // get the method printTime via Reflection & call it
                    Method theMethod = theInstance.getClass().getMethod("printTime", null);
                    theMethod.invoke( theInstance, null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
            } catch (Exception e) {
                e.printStackTrace();
    
            }
        }
    
        // the class loader
        public static class ByteClassLoader extends ClassLoader {
    
            public Class findClass(String name, byte[] data) {
                return defineClass(name, data, 0, data.length);
            }
        }
    }