OpenNTF / org.openntf.domino

Open replacement for lotus.domino package in HCL Domino
Apache License 2.0
65 stars 34 forks source link

Stack overflow on foreach (for) java statement #113

Closed jcornaz closed 8 years ago

jcornaz commented 10 years ago

Hello,

This code produce a stack overflow :

Session session = getSession();
Database db = session.getCurrentDatabase();
DocumentCollection col = db.search("Form = \"test\"");

// Trouble start here, while the for statement call iterator() mothod of the collection.
for (Document curDoc : col) {
      System.out.println(curDoc.getUniversalID());
}

The only working way to do it is that :

Document doc = col.getFirstDocument();
while (doc != null) {
      System.out.println(doc.getUniversalID());
      doc = col.getNextDocument(doc);
}

But this second code isn't good. First because one of the reason that why we'd like to use OpenNFT Domino API, is to don't have to write like that anymore. And second, because the "getNextDocument" method of OpenNTF Domino API is deprecated.

For more details, there is the exception stack trace :

Throwable occurred: java.lang.StackOverflowError
    at lotus.domino.local.NotesBase.<init>(Unknown Source)
    at lotus.domino.local.NoteCollection.<init>(Unknown Source)
    at lotus.domino.local.Session.FindOrCreate(Unknown Source)
    at lotus.domino.local.Session.FindOrCreate(Unknown Source)
    at lotus.domino.local.Database.createNoteCollection(Unknown Source)
    at org.openntf.domino.impl.Database.createNoteCollection(Database.java:485)
    at org.openntf.domino.impl.Database.createNoteCollection(Database.java:1)
    at org.openntf.domino.impl.DocumentCollection.toLotusNoteCollection(DocumentCollection.java:82)
    at org.openntf.domino.iterators.DocumentIterator.getCollectionIds(DocumentIterator.java:70)
    at org.openntf.domino.iterators.DocumentIterator.<init>(DocumentIterator.java:53)
[...]
    at org.openntf.domino.iterators.DocumentIterator.getCollectionIds(DocumentIterator.java:70)
    at org.openntf.domino.iterators.DocumentIterator.<init>(DocumentIterator.java:53)
    at org.openntf.domino.impl.DocumentCollection.iterator(DocumentCollection.java:747)
    at org.openntf.domino.impl.NoteCollection.add(NoteCollection.java:159)
    at org.openntf.domino.impl.DocumentCollection.toLotusNoteCollection(DocumentCollection.java:83)
    at org.openntf.domino.iterators.DocumentIterator.getCollectionIds(DocumentIterator.java:70)
    at org.openntf.domino.iterators.DocumentIterator.<init>(DocumentIterator.java:53)
    at org.openntf.domino.impl.DocumentCollection.iterator(DocumentCollection.java:747)
    at org.openntf.domino.impl.NoteCollection.add(NoteCollection.java:159)
    at org.openntf.domino.impl.DocumentCollection.toLotusNoteCollection(DocumentCollection.java:83)
    at org.openntf.domino.iterators.DocumentIterator.getCollectionIds(DocumentIterator.java:70)
    at org.openntf.domino.iterators.DocumentIterator.<init>(DocumentIterator.java:53)
    at org.openntf.domino.impl.DocumentCollection.iterator(DocumentCollection.java:747)
    at JavaAgent.NotesMain(Unknown Source)
    at lotus.domino.AgentBase.runNotes(Unknown Source)
    at lotus.domino.NotesThread.run(Unknown Source)
paulswithers commented 10 years ago

Can you let me know which release of the API this is for? Can I double-check what your getSession() method is doing?

I've tested it with godMode set to true and Session session = Factory.getSession(). With the latest version of the API it works and I also have an older version on an R9.0 server that works. It looks strange that it's failing in creating a NoteCollection for the iterator to process. That's not somethig I've encountered with any version of the API.

It would also be useful if you could test with the demo database http://www.intec.co.uk/wp-content/uploads/2013/09/OpenNTFDomino.zip. From the home page, you'll need to load the documents by clicking on the link to Administration at the bottom. Then if you go back to Home, then View. On any of the pages under that area go to the Java tab and click on the "Run Java Tests" button. They all iterate through documents using a for loop and this was used when developing and demo-ing M4.5. The only difference is the application uses GodMode, so it just uses ExtLibUtil.resolveVariable to get the database variable to access the current database.

jcornaz commented 10 years ago

Yes, I'm using the latest release of the API. I have checked it out from the master branch of this git repository. I am runing it from a R9 client and the database is on a R9 server.

The exception occurs even with the demo database with, the "org.openntf.domino.xsp=godmode,raid" Xsp Properties and if I do Session session = Factory.getSession().

If you think the session is in cause, I have got this log about the Session construction :

Resetting default local session because it was null
2014-05-16T13:22:36 [WARNING]: lotus.domino.local.NotesBase.<init> - null
***See IBM_TECHNICAL_SUPPORT\org.openntf.log.X.Y.txt for full stack trace***
16 mai 2014 13:22:36 org.openntf.domino.utils.DominoUtils$4 run
WARNING: null

But I don't understand how the iterator constructor could be impacted by the session. Especialy as it work with the old school "while" loop.

Please note, I haven't be able to prepare the demo database because the home page displays :

Error 500
Unexpected error condition

Therefore, I'm not directly intersted by XPages. I just want to write and run nice java code.

Thank you for your help

paulswithers commented 10 years ago

The master branch is the last published version, so M4.5. That will need this version of the demo database http://www.intec.co.uk/wp-content/uploads/2013/09/OpenNTFDomino.zip. We've added in new pickers and other functionality at the moment. If you want the latest development code, feel free to use my branch. I've been keeping it up-to-date with the work of the other developers.

Is it R9 or R9.0.1? There were some new classes added by IBM in 9.0.1, which may prevent it running. Here is a link to an up-to-date version for R9 which I'm using for development https://www.dropbox.com/s/ou6pmzdh5pzvc42/org.openntf.domino.9.0.zip

Looking at the code, the iterator creates a NoteCollection to add the NoteIDs of the Documents from the DocumentCollection to. From the stack trace, that's the bit it's failing on (shown from the first few lines), which explains why the while loop works fine. The NoteCollection is a child of the session, which is why I'm thinking that might be a problem.

The full stack trace of that error with DominoUtils gets written to a file in IBM_TECHNICAL_SUPPORT. The latest file is org.openntf.0.0.log (we just move the logs to a new file incrementing the numbers when the log gets full).

jcornaz commented 10 years ago

Our Notes/Domino is It's R9.0.1.

But, thank you because it works with your branch!

markleusink commented 10 years ago

I'm getting the same error with the API when I try to loop over a DocumentCollection (tested also with the demo database that you've linked to). The first time I run the sample I see this in the console:

screen shot 2014-05-22 at 14 47 16

If I then run the same code again the log fills up. It starts with:

2014-05-22T14:48:19 [WARNING]: sun.reflect.DelegatingMethodAccessorImpl.invoke - null
java.lang.StackOverflowError
    at     sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
    at java.lang.reflect.Method.invoke(Method.java:611)
    at org.openntf.domino.impl.Base.getLotusId(Base.java:214)
    at org.openntf.domino.impl.Base.<init>(Base.java:165)
    at org.openntf.domino.impl.NoteCollection.<init>(NoteCollection.java:89)
    at org.openntf.domino.utils.Factory.fromLotus(Factory.java:440)
    at org.openntf.domino.impl.Database.createNoteCollection(Database.java:485)
at org.openntf.domino.impl.Database.createNoteCollection(Database.java:56)
at org.openntf.domino.impl.DocumentCollection.toLotusNoteCollection(DocumentCollection.java:82)

I'm using milestone 4.5 (downloaded from OpenNTF) on a Domino 9.0.1 server. I also have v3 of the ExtLib installed, POI4XPages, the debug toolbar and Bootstrap4XPages. I've tried running it with all plugins (except the API disabled): result is the same.

If this has been fixed in your branch (as Melaes mentions): do you have a date when to expect a new release?

paulswithers commented 10 years ago

It looks like it's caused by iterating over an empty collection. Does that explain your scenario?

I'm not sure when a new release if due out, but in the mean time, one option is to check before iterating the collection.

markleusink commented 10 years ago

Nope. That doesn't explain it. If I do a while loop over the same DocumentCollection it works just fine.

This code works:

 public static void loopWhileDocCol() throws NotesException {

    System.out.println("test 5: while loop over DocCol containing all docs");

    Session s = Factory.getSession();
    Database db = s.getCurrentDatabase();
    DocumentCollection dc = db.getAllDocuments();

    System.out.println("- found " + dc.getCount() + " users (" + dc.size() + ")");

    Document doc = dc.getFirstDocument();
    while (null != doc) {
        System.out.println("> entry: " + doc.getNoteID());

        Document tmp = dc.getNextDocument(doc);
        doc.recycle();
        doc = tmp;
    }
}

This doesn't:

public static void loopForDocCol() throws NotesException {

    System.out.println("test 3: for loop over DocCol containing all docs");

    Session s = Factory.getSession();
    Database db = s.getCurrentDatabase();
    DocumentCollection dc = db.getAllDocuments();

    System.out.println("- found " + dc.getCount() + " users (" + dc.size() + ")");

    for (Document doc : dc) {
        System.out.println("> entry: " + doc.getNoteID());
    }
}
jwitthoff commented 10 years ago

After upgrading my development server to 9.0.1 FP1, I ran into the same problem. The same code works fine on our production server running 9.0. Loading the version posted by paulswithers above instead of the openntf essentials version fixed the problem.

wolfgang-herder-agi commented 9 years ago

Yeah, simply iterating over a View (e.g. People in names.nsf) causes the error:

    for (Document doc : vw.getAllDocuments()) {
        System.out.println(doc.getItemValue("Last Name", String.class));
    }

Paul's version works fine.