The great Marky Roden has written an interesting article about using the WebContent folder instead of standard domino design elements. To create or manipulate these files programmatically, you can use the Java NAPI.
The first example demonstrates the creation of a file using a Java Agent. Before you can compile the code, you have to import the required jars as described here.
import lotus.domino.AgentBase;
import com.ibm.designer.domino.napi.NotesConstants;
import com.ibm.designer.domino.napi.NotesDatabase;
import com.ibm.designer.domino.napi.NotesNote;
import com.ibm.designer.domino.napi.NotesSession;
import com.ibm.designer.domino.napi.design.FileAccess;
import com.ibm.jvm.util.ByteArrayOutputStream;
public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
final String serverName = "Dev01/Hasselba/CH";
final String dbPath = "NAPI.nsf";
final String fileName = "dummy.txt";
NotesSession nSession = new NotesSession();
NotesDatabase nDatabase = nSession.getDatabaseByPath(serverName
+ "!!" + dbPath);
nDatabase.open();
// create a new note
NotesNote nNote = nDatabase.createNote();
// define $Flags item
StringBuffer flags = new StringBuffer();
flags.append(NotesConstants.DESIGN_FLAG_HIDEFROMDESIGNLIST);
flags.append(NotesConstants.DESIGN_FLAG_NO_COMPOSE);
flags.append(NotesConstants.DESIGN_FLAG_HIDE_FROM_V4);
flags.append(NotesConstants.DESIGN_FLAG_FILE);
// define $FlagsExt item
StringBuffer extFlags = new StringBuffer();
extFlags.append(NotesConstants.DESIGN_FLAGEXT_WEBCONTENTFILE);
// init the file with the flags
nNote.initAsFile(flags.toString(), extFlags.toString());
// add required fields
nNote.setItemText("$TITLE", fileName);
nNote.setItemText("$MimeType", "text/plain");
// generate some random data
ByteArrayOutputStream bos = new ByteArrayOutputStream();
for (int i = 0; i < 128000; i++) {
int hlp = (i % 24) + 60;
bos.write(hlp);
}
// store the data to the Note
FileAccess.saveData(nNote, fileName, bos.toByteArray());
// recycle the NAPI objects
nNote.recycle();
nDatabase.recycle();
nSession.recycle();
} catch (Exception e) {
e.printStackTrace();
}
}
}
As you can see, when using the NAPI you don’t have to save a note. It is directly written to the NSF.
After running the agent and refreshing the project explorer view (hit F9) the newly created file appears in the WebContent folder…
… and is accessible in the browser:
If you want to allow public access to your element, you have to add a single line in the code above:
nNote.setItemText("$PublicAccess", "1");
This allows unauthenticated users to access the file while the rest of the application is protected:
On the other hand, you can use reader fields enhance the security of the file. But this can not be done with the note object directly, you have to use the standard Domino document classes for this. To access the document, you have to convert the note’s note id (an integer value) into his hexadecimal representation:
int noteId = nNote.getNoteId();
Document doc = db.getDocumentByID(Integer.toHexString(noteId));
Then, you can add the reader field to the document and save the result.
Session session = getAgentSession();
Database db = session.getCurrentDatabase();
Document doc = db.getDocumentByID(Integer.toHexString(noteId));
// create the field
Item item = doc.replaceItemValue("DocReaders", "[ReadAll]");
item.setReaders(true);
// save the document
doc.save();
// recycle the instances
item.recycle();
doc.recycle();
db.recycle();
session.recycle();
Now, the file is protected when opening in the browser:
Keep in mind: As the developer it is required to have the access rights for the file too.
Now if we could build the application pragmatically could we „patch“applications via the UI ? 🙂
Yes, I will create an article about that asap.
wow, I didn’t realise it was possible – cool
Nice one, 2 remarks:
Change:
doc.replaceItemValue("DocReaders", "[ReadAll]");
Item item = doc.getFirstItem("DocReaders");
item.setReaders(true);
to
Item item = doc.replaceItemValue("DocReaders", "[ReadAll]");
item.setReaders(true);
Would that work on a Server? Are the napi classes there?
Sure, these are core classes for the XPages runtime.
Sven – you never cease to amaze 🙂
However unlikely, I hope we meet one day – I’d love to buy you a beer. It would be my pleasure 🙂
To me it only works the first time.
When I run the agent for the second time gives me this error:
[10A8:0039-013C] 24/11/2014 11.28.02 HTTP JVM: Exception in thread „AgentThread: JavaAgent“
[10A8:003A-013C] 24/11/2014 11.28.02 HTTP JVM: java.lang.UnsatisfiedLinkError: com/ibm/designer/domino/napi/NotesDatabase.NOpen(java/lang/String;)
[10A8:003C-013C] 24/11/2014 11.28.02 HTTP JVM: at com.ibm.designer.domino.napi.NotesDatabase.open(NotesDatabase.java:123)
[10A8:003E-013C] 24/11/2014 11.28.02 HTTP JVM: at JavaAgent.NotesMain(Unknown Source)
[10A8:0040-013C] 24/11/2014 11.28.02 HTTP JVM: at lotus.domino.AgentBase.runNotes(Unknown Source)
[10A8:0042-013C] 24/11/2014 11.28.02 HTTP JVM: at lotus.domino.NotesThread.run(Unknown Source)
[12E4:008F-0DC0] 24/11/2014 11.30.44 Opened session for Stefano Fois/Wolters Kluwer Italy (Release 9.0.1FP1)
Any idea?
thanks
I picked up this work recently.
But even with the latest version of domino have the same problem.
If you launch the agent works correctly the first time.
From the second time then I get the error: java.lang.UnsatisfiedLinkError.
This is done either by throwing the agent on the client or server side.
But it only happens to me? or is a known problem?
Thanks a lot.
Hello,
I have the same issue than Stefano.
The first time it works, and then java.lang.UnsatisfiedLinkError. I was not able to solve it yet. I’m running it on Domino 8.5.3, scheduled on server.