klehmann / domino-jna

Java project to access the IBM/HCL Domino C API using Java Native Access (JNA)
Apache License 2.0
68 stars 17 forks source link

java Environment #29

Open lmike-mnc opened 5 years ago

lmike-mnc commented 5 years ago

Hi Klehmann, Is it possible run java (standalone) program on domino server host (linux)? currently I've tried, but receive error: Initializing Domino JNA with mode Direct com.mindoo.domino.jna.errors.NotesError: Could not open the ID file (error code: 6402, raw error with all flags: 6402) on NotesDatabase dbData = new NotesDatabase(session, "", "fakenames.nsf");

java environment variables are: -DNOTESINI=/local/notesdata/notes.ini -DNOTESDATA=/loca/notes/data -Duser.dir=/local/notesdata java.library.path=/opt/ibm/domino/notes/latest/linux

thanks in advance Mike

klehmann commented 5 years ago

I haven't tested it but would expect that it works.

Did you call com.mindoo.domino.jna.utils.NotesInitUtils.notesInitExtended(String[]) at the start of your program and com.mindoo.domino.jna.utils.NotesInitUtils.notesTerm()at the end?

And for each Thread that is accessing Domino data, call com.mindoo.domino.jna.utils.NotesInitUtils.notesInitThread() at the start and com.mindoo.domino.jna.utils.NotesInitUtils.notesTermThread() at the end.

It's also important to wrap the code in a com.mindoo.domino.jna.gc.NotesGC.runWithAutoGC(Callable<T>)block.

lmike-mnc commented 5 years ago

I haven't tested it but would expect that it works.

Did you call com.mindoo.domino.jna.utils.NotesInitUtils.notesInitExtended(String[]) at the start of your program and com.mindoo.domino.jna.utils.NotesInitUtils.notesTerm()at the end?

And for each Thread that is accessing Domino data, call com.mindoo.domino.jna.utils.NotesInitUtils.notesInitThread() at the start and com.mindoo.domino.jna.utils.NotesInitUtils.notesTermThread() at the end.

It's also important to wrap the code in a com.mindoo.domino.jna.gc.NotesGC.runWithAutoGC(Callable<T>)block.

Thanks didn't ... I've only copy/past code from manual at your start page com.mindoo.domino.jna.utils.NotesInitUtils.notesInitExtended(String[]) what values should be in String array?

klehmann commented 5 years ago

Try new String[0]. These are the command line parameters to launch Notes. E.g. you could specify "=c:\temp\notes.ini" to set the Notes.ini path.

lmike-mnc commented 5 years ago

Try new String[0]. These are the command line parameters to launch Notes. E.g. you could specify "=c:\temp\notes.ini" to set the Notes.ini path.

Thank you a lot I'll try Small question - what will happen if only domino server present (client is absent) and it's running, and it's Linux platform (ubuntu distr)?

klehmann commented 5 years ago

What do you mean? Domino JNA would run with the server ID. Ubuntu is an unsupported platform for Domino btw. :-)

lmike-mnc commented 5 years ago

What do you mean? Domino JNA would run with the server ID.

yes true, but I have user ID (if it's necessary)

Ubuntu is an unsupported platform for Domino btw. :-)

unsupported but works :;)

klehmann commented 5 years ago

In general, you would not need it, since the server can switch user contexts when opening a database. E.g. use new NotesDatabase(String server, String filePath, String asUserCanonical) with asUserCanonical="" for the server ID user or with any Notesname for a different user context.

The specified username is used for read/write access checks and written into $UpdatedBy when saving documents.

There's one exception where you would need your ID file, which is encryption. By default, the server ID would be used to encrypt/decrypt data.

I am not sure how complete the APIs are to use a different ID file. There is com.mindoo.domino.jna.utils.IDUtils.openUserIdFile(String, String, IDAccessCallback<T>) to open an ID file and get a NotesUserId object back which can be used for signing (com.mindoo.domino.jna.NotesNote.sign(NotesUserId, boolean)) and encryption (com.mindoo.domino.jna.NotesNote.copyAndEncrypt(NotesUserId, EnumSet<EncryptionMode>) / com.mindoo.domino.jna.NotesNote.decrypt(NotesUserId)).

But I haven't really tested this so far.

lmike-mnc commented 5 years ago

Sorry, I've tried, but unsuccessfull :( my code

package com.setralubs;
import com.mindoo.domino.jna.*;
import com.mindoo.domino.jna.NotesCollection.EntriesAsListCallback;
import com.mindoo.domino.jna.constants.Navigate;
import com.mindoo.domino.jna.constants.OpenNote;
import com.mindoo.domino.jna.constants.ReadMask;
import com.mindoo.domino.jna.gc.NotesGC;
import lotus.domino.NotesException;
import lotus.domino.NotesFactory;
import lotus.domino.NotesThread;
import lotus.domino.Session;

import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.concurrent.Callable;

public class DominoApi{

    public static void main(String[] args) throws NotesException {
        System.out.println("-Djava.library.path="+System.getProperty("java.library.path"));
        System.out.println("-Duser.dir=" +
                System.getProperty("user.dir"));
        try {
            com.mindoo.domino.jna.utils.NotesInitUtils.notesInitExtended(new String[] {"/local/notesdata/notes.ini"});                    
            NotesGC.runWithAutoGC(new Callable<Object>() {

                @Override
                public Object call() throws Exception {
                    StopWatch stopWatch = new StopWatch();
                    NotesThread.sinitThread();
                    Session session = NotesFactory.createSession();
                    stopWatch.start();
                    NotesDatabase dbData = new NotesDatabase(session, "", "fakenames.nsf");
                    //NotesDatabase dbData = new NotesDatabase("dom2/CRUINTERNET", "fakenames.nsf", "dom2/CRUINTERNET");
                    NotesCollection colFromDbData = dbData.openCollectionByName("People");

                    boolean includeCategoryIds = false;
                    LinkedHashSet<Integer> allIds = colFromDbData.getAllIds(Navigate.ALL_DESCENDANTS);
                    NotesIDTable selectedList = colFromDbData.getSelectedList();
                    selectedList.clear();
                    selectedList.addNotes(allIds);
                    String startPos = "0";
                    int entriesToSkip = 1;
                    int entriesToReturn = Integer.MAX_VALUE;
                    EnumSet returnNavigator = EnumSet.of(Navigate.NEXT_SELECTED);
                    int bufferSize = Integer.MAX_VALUE;
                    EnumSet returnData = EnumSet.of(ReadMask.NOTEID, ReadMask.SUMMARY);

                    List<NotesViewEntryData> selectedEntries = colFromDbData.getAllEntries(startPos, entriesToSkip,
                            returnNavigator, bufferSize, returnData, new EntriesAsListCallback(entriesToReturn));

                    for (NotesViewEntryData currEntry : selectedEntries) {
                        NotesNote note = dbData.openNoteById(currEntry.getNoteId(), EnumSet.noneOf(OpenNote.class));

                        System.out.println(
                                note.getItemValueString("lastname") + ", " + note.getItemValueString("firstname"));
                        note.recycle();
                    }
                    stopWatch.stop();
                    System.out.println(stopWatch.getElapsedTimeSecs());
                    return null;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            NotesThread.stermThread();
            com.mindoo.domino.jna.utils.NotesInitUtils.notesTerm();
        }

    }
}

and result

-Djava.library.path=/opt/ibm/domino/notes/latest/linux -Duser.dir=/local/notesdata Initializing Domino JNA with mode Direct com.mindoo.domino.jna.errors.NotesError: Error initializing Notes connection at com.mindoo.domino.jna.utils.NotesInitUtils.notesInitExtended(NotesInitUtils.java:46) at com.setralubs.DominoApi.main(DominoApi.java:25) Exception in thread "main" java.lang.NullPointerException at lotus.domino.local.NotesReferenceQueue.decThreadCount(Unknown Source) at lotus.domino.NotesThread.stermThread(Unknown Source) at com.setralubs.DominoApi.main(DominoApi.java:68)

lmike-mnc commented 5 years ago

And for each Thread that is accessing Domino data, call com.mindoo.domino.jna.utils.NotesInitUtils.notesInitThread() at the start and com.mindoo.domino.jna.utils.NotesInitUtils.notesTermThread() at the end.

@klehmann thanks again... that works with small details for domino server: com.mindoo.domino.jna.utils.NotesInitUtils.notesTermThread() will initiate server shutdown (if it's started). I've had such behavior one time com.mindoo.domino.jna.utils.NotesInitUtils.notesInitThread() I can't use with any strings in array exept new String[]{} or new String[0]

In general, you would not need it, since the server can switch user contexts when opening a database. E.g. use new NotesDatabase(String server, String filePath, String asUserCanonical) with asUserCanonical="" for the server ID user or with any Notesname for a different user context.

with any user (and blank) selectedEntries is Empty

klehmann commented 5 years ago

Regarding the NullPointerException, got that here as well with the R11 beta. Found out that the order of stermThread/NotesTerm is wrong in my unit test. See fb61763f7e8dad2dd96aeb67facf506017432c03

And I remember seeing this server shutdown, probably because the server things that a subprocess has terminated abnormally. Could you please check if this changed order fixes this behavior? I'm quite busy these days, will probably take some time to run the API against a server on my machine.

lmike-mnc commented 5 years ago

Klehmann Thank you

Regarding the NullPointerException, got that here as well with the R11 beta. Found out that the order of stermThread/NotesTerm is wrong in my unit test. See fb61763

this has happened when I've tried use parameters as com.mindoo.domino.jna.utils.NotesInitUtils.notesInitExtended(new String[]{"/local/notesdatanotes.ini"}); I've tired today and have received core dump on

com.mindoo.domino.jna.errors.NotesError: Error initializing Notes connection at com.mindoo.domino.jna.utils.NotesInitUtils.notesInitExtended(NotesInitUtils.java:46)

with com.mindoo.domino.jna.utils.NotesInitUtils.notesInitExtended(new String[]{}); all are working, except colFromDbData.getAllEntries(startPos, entriesToSkip, returnNavigator, bufferSize, returnData, new EntriesAsListCallback(entriesToReturn)); return empty list... here my code

import com.mindoo.domino.jna.NotesCollection.EntriesAsListCallback;
import com.mindoo.domino.jna.constants.Navigate;
import com.mindoo.domino.jna.constants.OpenNote;
import com.mindoo.domino.jna.constants.ReadMask;
import com.mindoo.domino.jna.gc.NotesGC;
import lotus.domino.NotesException;
import lotus.domino.NotesFactory;
import lotus.domino.NotesThread;
import lotus.domino.Session;

import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.concurrent.Callable;

public class DominoApi{

    public static void main(String[] args) throws NotesException {
        System.out.println("-Djava.library.path="+System.getProperty("java.library.path"));
        System.out.println("-Duser.dir=" +
                System.getProperty("user.dir"));
        try {
            //initialize domino instance
            com.mindoo.domino.jna.utils.NotesInitUtils.notesInitExtended(new String[]{});
            //com.mindoo.domino.jna.utils.NotesInitUtils.notesInitExtended(new String[]{"/local/notesdata/notes.ini"});
            NotesGC.runWithAutoGC(new Callable<Object>() {

                @Override
                public Object call() throws Exception {
                    StopWatch stopWatch = new StopWatch();
                    //NotesThread.sinitThread();//not necessary
                    //Session session = NotesFactory.createSession();//not necessary
                    stopWatch.start();
                    //NotesDatabase dbData = new NotesDatabase(session, "", "names.nsf");//not necessary
                    //NotesDatabase dbData = new NotesDatabase("CN=mail1/O=CRUINTERNET", "names.nsf", "CN=mail1/O=CRUINTERNET");
                    //NotesDatabase dbData = new NotesDatabase("CN=mail1/O=CRUINTERNET", "names.nsf", "");
                    //NotesDatabase dbData = new NotesDatabase("", "names.nsf", "CN=admin/O=CRUINTERNET");
                    NotesDatabase dbData = new NotesDatabase("", "names.nsf", "");
                    System.out.println("Db server: "+dbData.getServer());
                    System.out.println("Context User: "+dbData.getContextUser());
                    NotesCollection colFromDbData = dbData.openCollectionByName("People");

                    boolean includeCategoryIds = false;
                    LinkedHashSet<Integer> allIds = colFromDbData.getAllIds(Navigate.ALL_DESCENDANTS);
                    NotesIDTable selectedList = colFromDbData.getSelectedList();
                    selectedList.clear();
                    selectedList.addNotes(allIds);
                    String startPos = "0";
                    int entriesToSkip = 1;
                    int entriesToReturn = Integer.MAX_VALUE;
                    EnumSet returnNavigator = EnumSet.of(Navigate.NEXT_SELECTED);
                    int bufferSize = Integer.MAX_VALUE;
                    EnumSet returnData = EnumSet.of(ReadMask.NOTEID, ReadMask.SUMMARY);

                    List<NotesViewEntryData> selectedEntries = colFromDbData.getAllEntries(startPos, entriesToSkip,
                            returnNavigator, bufferSize, returnData, new EntriesAsListCallback(entriesToReturn));
                    System.out.println("Entries count:" + selectedEntries.size());
                    for (NotesViewEntryData currEntry : selectedEntries) {
                        NotesNote note = dbData.openNoteById(currEntry.getNoteId(), EnumSet.noneOf(OpenNote.class));

                        System.out.println(
                                note.getItemValueString("lastname") + ", " + note.getItemValueString("firstname"));
                        note.recycle();
                    }
                    stopWatch.stop();
                    System.out.println(stopWatch.getElapsedTimeSecs());
                    return null;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //NotesThread.stermThread();//not necessary
            //terminate domino instance
            com.mindoo.domino.jna.utils.NotesInitUtils.notesTerm();
        }

    }

}

follow to result

-Djava.library.path=/opt/ibm/domino/notes/latest/linux -Duser.dir=/local/notesdata Initializing Domino JNA with mode Direct 0E:AA (0 MB): 100% 19.09.2019 14:04:27 0E:A8 19.09.2019 14:04:27 03:3E 19.09.2019 14:04:27 03:3E Db server: Context User: CN=dom2/O=CRUINTERNET Entries count:0 1090054

klehmann commented 5 years ago

Please check if allIds contains any values.

LinkedHashSet<Integer> allIds = colFromDbData.getAllIds(Navigate.ALL_DESCENDANTS);

Using ALL_DESCENDANTS here does not really make sense. Haven't tried that one in this context. Try Navigate.NEXT_NONCATEGORY to read all documents or Navigate.NEXT to read category note ids as well.

lmike-mnc commented 5 years ago

Please check if allIds contains any values.

LinkedHashSet<Integer> allIds = colFromDbData.getAllIds(Navigate.ALL_DESCENDANTS);

Using ALL_DESCENDANTS here does not really make sense. Haven't tried that one in this context. Try Navigate.NEXT_NONCATEGORY to read all documents or Navigate.NEXT to read category note ids as well.

thnx it's working :)

klehmann commented 5 years ago

I created a sample standalone app that is working on my Mac (running in Eclipse): https://github.com/klehmann/domino-jna/tree/master/standalone-app-sample

Haven‘t checked yet what happens on a Domino server.

lmike-mnc commented 5 years ago

I created a sample standalone app that is working on my Mac (running in Eclipse): https://github.com/klehmann/domino-jna/tree/master/standalone-app-sample

Thanks , it's very helpful

klehmann commented 5 years ago

Just noticed that your notesInitExtended arguments seem to be wrong. The first one should be the Notes program directory and the second one "=" + the path to the Notes.ini.

See http://www-12.lotus.com/ldd/doc/domino_notes/9.0/api90ref.nsf/61fd4e9848264ad28525620b006ba8bd/e151a8f6c224633d85255f7f00664516?OpenDocument for the C method documentation.

That's what I am doing in my JUnit base class: https://github.com/klehmann/domino-jna/blob/master/domino-jna/src/test/java/com/mindoo/domino/jna/test/BaseJNATestClass.java#L58

lmike-mnc commented 5 years ago

Thanks main issue is server environment, I don't remember notes.ini as parameter for server binary. So I think it's not possible to use notes.ini path for me