Mindoo Blog - Cutting edge technologies - About Java, Lotus Notes and iPhone

  • Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    Karsten Lehmann  11 October 2009 17:46:06
    Disclaimer: IBM Lotus Notes/Domino 8.5.1 is prerelease code and there are no guarantees from IBM that the functionality presented or discussed will be in the final shipping product.


    I haven't read any blog articles yet about the new extensibility APIs that come with Lotus Notes 8.5.1. Since we participated in the discussion with IBM (at Lotusphere 2009 and later on in the Design Partner Program) about what needs to be part of a first official API version, I would like to give you some hints where to find these new APIs and what they are about.

    Two new extensibility APIs will ship with Lotus Notes 8.5.1:

    Domino Designer Extensibility API
    With this API, an experienced Eclipse Java developer is able to track the user's selection in DDE (e.g. the Note ID/Notes URL of the selected design elements) in order to apply his own design modifications (e.g. via DXL import) and let DDE catch up with the modified design elements afterwards.
    It contains functions to convert a standard Eclipse IProject into something called DesignerProject that provides additional information for a NSF database project in DDE. You get the basic NSF data like server/filepath/replica-id, some design related infos (template names, design hidden flag) and a few interaction methods, for example to open a database in DDE and to initialize/refresh the whole NSF project or single design elements in case you applied some changes to the backend Notes database.

    Notes Client Java UI API
    The Java UI API lets you get a handle on the currently opened UI document and UI view, called NotesUIDocument / NotesUIView:

    NotesUIWorkspace ws=new NotesUIWorkspace();
    NotesUIDocument uidoc=ws.getCurrentDocument();
    NotesUIView uiview=ws.getCurrentView();


    You do not have all the methods in Java yet that you know from the Lotusscript NotesUIDocument/NotesUIView, so don't expect too much for round nr 1. (But read on until the last paragraph to see why this is not a real problem)

    NotesUIDocument
    With the Java based NotesUIDocument you are able to modify fields in the backend document. It provides refresh methods to make those changes visible in the front end.
    Please note, that I said "modify fields", not "get the backend document". There are technical reasons (for example running in different threads and the Client's memory management) that make it impossible to get a full handle on the backend document, but the functionality of the API should be enough for most of the use cases.

    You can get information about the currently focused field (including tracking focus changes with a DocumentFieldListener), toggle edit mode on/off, cut/copy/paste/insert text in the UI and detect that a document has been modified.

    NotesUIView
    The NotesUIView class gives you access to the view's name/UNID/URL. There is a method to print the view.

    That not much for the NotesUIView, but by using the available Eclipse selection APIs you were already able to grab the selected documents in earlier Lotus Notes versions.

    NotesUIWorkspace
    In addition to the methods getCurrentDocument() and getCurrentView(), NotesUIWorkspace contains various methods to open Notes contents, like views, framesets or pages. There are also a few compose(...) methods that open a form to create a document in the Notes client. You can optionally specify a Document as an argument that contains fields that should be set as default field values in the form (this document can be a temporary document created with NotesUIWorkspace.getTemporaryDocument(Session)that is automatically deleted when the Notes client shuts down).
    NotesUIWorkspace.addDatabase(...) adds a database to the workspace of the Notes client.
    And finally, there is a NotesUIWorkspace.prompt(...) method that works like the corresponding method in Lotusscript. That means it displays different forms of selection dialogs with the style of the Notes client.

    Need more information?
    So, how do you know the exact syntax of the available classes and methods?
    You can find the complete Javadoc documentation for the two new APIs in the help system of the Lotus Notes client:

    Image:Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    There is one more thing :-)
    Oh wait, I forgot one method. Actually, it's my favorit one.
    When we saw the first draft of the Java UI API at the end of last year, we thought of many things that we would like to add.
    But you know, you quickly realize that you can only concentrate on a few features or even a single one, that is the most important to you and needs to be available for round nr 1.

    Together with a few other design partners, we desperately asked/begged IBM to add one method, that is mission critical for the success of the API release.

    The basic question was: What would you do if a feature is not available in Java, but you know that it's there in Lotusscript? You write a Lotusscript agent and call it from Java.
    Something like

    Database db=session.getDatabase(server, filepath);
    Agent myAgent=db.getAgent("MyLotusscriptAgent");
    myAgent.run();


    That's nothing new. A standard function in the Notes Java API sind R5 or R6.

    Ever tried that with an agent that should do something in the UI, like changing a form's field values or open a selection dialog?
    It does not work.

    That's because Lotus Notes only executes that code in the backend, you do not have any UI access.

    Here is the solution:

    public void runAgent(NotesAgentData agentData, NotesDocumentDataCallback callback, boolean runOnUIContext)
    From the javadoc:
    Runs the agent represented by the agent data. Pass in false for runOnUIContext to run your agent on a temporary document. Pass in true for runOnUIContext to run your agent on the current selected document in the UI. Values added to the NotesAgentData object, using the addItem method, will be added to the temporary document. Also note with this method you can run an agent from one database on a completely different database. In other words, the agent you are running does not have to run on documents from the same database. While this gives the user more flexibility it also may break some assumptions of the agent, for example what fields are on the document.

    When running an agent on a temporary document it is recommended that you set the Target in the properties dialog of the agent to be 'None'. You can do this while editing the agent in Domino Designer. This allows you to run the agent without having anything selected in the UI. To access the temporary document from your agent, you can use Session.DocumentContext in LotusScript, or Session.getAgentContext().getDocumentContext() in Java. The note id of the temporary document is returned to you in the NotesDocumentDataCallback object.
    [...]
    Parameters:
    agentData - data about the agent to run
    callback - callback to run when agent is done running
    runOnUIContext - true to run the agent on the current UI context false to run the agent on the temporary document


    This new method is incredibly great.

    It means that you can put all the code that is missing in this first Java UI API release into a Lotusscript or formula agent and use NotesUIWorkspace.runAgent() to execute it -  in any database. And even better, there is a callback mechanism that you can use to get notified when the code is done to grab some results from a parameter document or the Notes.ini.


    Tomorrow is Notes 8.5.1 release day. Have fun playing with the new APIs!

    Comments

    1Bob Balfe  11.10.2009 22:32:19  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    Great posting Karsten! There is a CA Wiki article that shows how you can have an agent called using that same API:

    { Link }

    Using the same technique you describe here you can pass data to the agent from another component.

    2Karsten Lehmann  11.10.2009 23:40:57  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    Thanks Bob!

    I especially like the fact that even if I let the agent run on a non-UI context (runOnUIContext=false), I can get access to the NotesUIDocument by using

    Dim ws as New NotesUIWorkspace

    dim uidoc as NotesUIDocument

    set uidoc=ws.CurrentDocument

    in Lotusscript. That way, we can pass parameters to the agent and still interact with the current UI document.

    3Karsten Lehmann  22.10.2009 16:00:28  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    An additional information, because I just read postings of confused users in the 8.5 forum:

    The Java UI classes are only available for Eclipse plugin development.

    You cannot use them in classic Java agents or Java libraries.

    4Xuesong Wen  19.11.2009 14:28:36  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    Hi Karsten,

    At end of this blog, you said that "there is a callback mechanism that you can use to get notified when the code is done to grab some results from a parameter document or the Notes.ini. "

    But how to grab results from a parameter document? I have tried, it doesn't work. Here is some code:

    NotesDocumentDataCallback doc = new NotesDocumentDataCallback(){

    public void done(NotesDocumentDataEvent arg0) {

    NotesDocumentData ndd = arg0.getDocumentData();

    ......

    super.done(arg0);

    }

    };

    but how can I get items in this document with NotesDocumentData object?

    P.S. Ops....Sorry for the comments above, there was something wrong with my browser, I was still writing comment, suddenly browser was blocked, and then.... two comments were already there. :( Please delete them, if you can.

    5Karsten Lehmann  19.11.2009 16:06:32  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    Hi!

    Ok, no problem, I deleted the other two comments.

    Here is how to pass parameters between the Java UI classes and a Lotuscript agent:

    In an Eclipse toolbar action, you can use this code to call the agent:

    public void run(IAction action) {

    try {

    NotesUIWorkspace w=new NotesUIWorkspace();

    NotesDatabaseData dbData = new NotesDatabaseData("Server/Company", "path/to/database.nsf");

    NotesAgentData agentData=new NotesAgentData(dbData, "TestAgent1");

    agentData.addItem("Name", "Karsten Lehmann");

    NotesDocumentDataCallback agentCallback=new NotesDocumentDataCallback() {

    public void done(NotesDocumentDataEvent evt) {

    displayAgentResult(evt);

    }

    };

    w.runAgent(agentData, agentCallback, false);

    } catch (NotesException e) {

    e.printStackTrace();

    }

    }

    The method runAgent() in the UI classes internally starts a new NotesSessionJob in the background to do the actual agent invocation (the method does not block).

    When the agent execution is done, the agent callback function calls the method "displayAgentResult":

    protected void displayAgentResult(NotesDocumentDataEvent agentResult) {

    final NotesException ex=agentResult.getError();

    if (ex!=null) {

    UIJob displayResult=new UIJob("Display document result") {

    public IStatus runInUIThread(IProgressMonitor arg0) {

    Shell shell=Display.getDefault().getActiveShell();

    MessageDialog.openInformation(shell, "Agent result", "The agent produced an error: "+ex.getMessage());

    return Status.OK_STATUS;

    }

    };

    displayResult.schedule();

    }

    else {

    final NotesDocumentData docData=agentResult.getDocumentData();

    NotesSessionJob fetchDocJob=new NotesSessionJob("Fetching the agent result document") {

    protected IStatus runInNotesThread(Session session,IProgressMonitor progress) throws NotesException {

    Document doc=docData.open(session);

    final String agentResult=doc.getItemValueString("Result");

    UIJob displayResult=new UIJob("Display document result") {

    public IStatus runInUIThread(IProgressMonitor progress2) {

    Shell shell=Display.getDefault().getActiveShell();

    MessageDialog.openInformation(shell, "Agent result", "The agent returned: "+agentResult);

    return Status.OK_STATUS;

    }

    };

    displayResult.schedule();

    return Status.OK_STATUS;

    }

    };

    fetchDocJob.schedule();

    }

    };

    In my Lotusscript agent, I used the following code to read the input parameter and return a result value:

    Sub Initialize()

    Dim session As New NotesSession

    Dim context As NotesDocument

    Dim inputParam As String

    Set context=session.Documentcontext

    inputParam=context.Name(0)

    context.Result="Hello "+inputParam+"!"

    context.save True,false

    End Sub

    The example displays a dialog box with "Hello Karsten Lehmann!".

    6Karsten Lehmann  19.11.2009 16:08:17  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    I hope you can read the code. It lost the formatting and tabs.

    7Xuesong Wen  19.11.2009 19:19:10  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    Thanks, it works:) "Document doc=docData.open(session);" that is what I want.

    8Carl  05.03.2010 16:28:18  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    Using this, could I refresh the current UI View with a sidebar plugin?

    I have a plugin that supports drag and drop deletion, the plugin deletes the dropped documents fine, but how do I refresh the view in the UI to reflect that deletion?

    Many thanks

    Carl

    9Karsten Lehmann  05.03.2010 16:38:06  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    Yes, this can be done, although there is no direct NotesUIView.refresh call yet (we already requested that at IBM dev).

    You could put some Lotusscript code to refresh your view in an agent and execute it from NotesUIWorkspace.runAgent.

    If that does not help, because the viewpart with the view is not focused (haven't tried), you could try to get a handle on the view by calling NotesUIWorkspace.getCurrentView() in Java and then call NotesUIView.activate(), before you run the agent.

    10Carl  05.03.2010 17:22:08  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    Thanks Karsten.

    I thought I could do that, I was trying to avoid having to put an agent into a database as that complicates the deployment.

    Thank you very much for your quick response!

    Carl

    11Karsten Lehmann  05.03.2010 18:23:57  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    I haven't tried it yet, but it may be possible that you store such a tool database in your Eclipse plugin and deploy it on demand to the client machine in your plugin code (e.g. in a temporary folder). Plugins are not restricted, so a File operation should not be a problem.

    Another not-so-friendly approach could be a DXL import into the temporary database that the UI API is using (NotesUIWorkspace.getTemporaryDocument().getParent()).

    12Jonas  25.01.2012 08:41:54  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    Hi Karsten

    Can see in the comments from this link: { Link }

    that you have created an example doing a refresh using the dxl import.

    Would you mind publish that example?

    I would appreciate that...

    - Jonas

    13Karsten Lehmann  25.01.2012 09:19:57  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    Hi Jonas,

    thanks for the feedback. Creating such a demo is now on my list. Can't promise when this will be ready, because I need to work on it in the evenings or on weekends (no time during the day because of project work).

    Best regards,

    Karsten

    14Joseph B LeMay  14.10.2013 02:25:28  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    So is there a trick to update a notes ui document from a java agent? since this stuff only works for plugins, I can't use it in an agent.

    15Karsten Lehmann  15.10.2013 09:19:58  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    There is no trick and no easy solution. You cannot use the UI API from a Java agent.

    Might be possible to build a bridge to do it, e.g. put a jar in jvm/lib/ext with Java classes that you can call from the agent and that forward the calls to Eclipse plugin, but the main problem would be deadlocks, at least if the Java agent gets called from UI code in LotusScript or formula language.

    In that case, the UI code waits for the agent to finish executing and the agent itself tries to change UI stuff (=send commands to the Notes UI thread which is already waiting for the agent).

    That cannot work. All would need to be implemented asynchronously to avoid this deadlock, e.g. by setting the agent flag to run it in the background.

    16Joseph B LeMay  16.10.2013 01:28:37  Notes 8.5.1: The new Java UI classes and Domino Designer extensibility API

    OK, so I'll just write the thing I'm doing as a plugin. I made a dialog box in java because I wanted to be able to do some things I could not do with the Notes LotusScript UI classes.