I am working on a simple Java code to extract all calendar entries for a given date. I know it's possible using Domingo but I would like to use only Notes.jar for this purpose. It is possible for me to create a session based on a given credentials and get the calendar object. I am looking to extract the current running Notes session and use that session object to open the calendar view in the mail file and start playing with it. But I am not able to get it working. Anybody have any idea or links on this?
Well I have done with the default notes API and here's the code.
NotesAPITest nat = new NotesAPITest();
NotesThread.sinitThread();
Session sess1 = NotesFactory.createSession();
System.out.println(sess1.getUserName());
Database database = sess1.getDatabase("", "mailfile");
View calendarView = database.getView("($Calendar)");
DateTime dt = sess1.createDateTime("today");
ViewEntryCollection vec = calendarView.getAllEntriesByKey(dt, true);
ViewEntry entry = vec.getFirstEntry();
while (entry != null)
{
Document caldoc = entry.getDocument();
System.out.println("Subject: " + caldoc.getItemValueString("Subject"));
System.out.println("Chair Person: " + caldoc.getItemValueString("Chair"));
System.out.println("Start Time: " + nat.getStartEndTimes(caldoc, "StartDateTime") );
System.out.println("Start Time: " + nat.getStartEndTimes(caldoc, "EndDateTime") );
System.out.println("Required: " + caldoc.getItemValueString("RequiredAttendees"));
entry = vec.getNextEntry();
}
The only drawback i see is that, whenever the session is extracte, notes pops up a password dialog box. In my searches so far I have not seen a solution for that. Apparently a security arrangement in LN i guess.
Just by googling I have found this article. They create an Eclispe plugin there for Notes. And the example code for getting employee brithdays is also there (I guess Calendar works in a similar way):
s = NotesFactory.createSession();
// Get the local address book
Database nab = s.getDatabase("",s.getAddressBooks().elementAt(0).toString());
if (nab.isOpen() == false) nab.open();
// Get the Birthdays & Anniversaries view
View baview = nab.getView("BA");
ViewEntryCollection eba = baview.getAllEntries();
ViewEntry entry = eba.getFirstEntry();
list = new String[eba.getCount()];
int count = 0;
while (entry != null) {
Vector vals = entry.getColumnValues();
list[count]= vals.elementAt(1).toString() + " " + vals.elementAt(2).toString();
entry = eba.getNextEntry();
count++;
}
EDIT: Also look at this link for some documentation on Notes.jar.
The NotesFactory.createSession() method is what you can use to get a handle to the current session. Notes will automatically share the current client session. If this method is failing, there may be something wrong with your basic configuration. Be sure that:
You have the Notes Client fully installed on the machine running the Java app, and be sure there is a valid Notes ID file. (For example, be sure you can open the Notes client on this machine successfully).
Also, be sure that the the nnotes.dll file is accessible on your machine's path (different than the Java CLASSPATH).
And, confirm that the Notes.ini file is also on the machine's PATH.
#vikramjb, try doing NotesFactory.createSession((String) null, (String) null, password); to prevent the notes password popup from prompting you each time you do something with the session that needs security.
Found out about this from here: http://lekkimworld.com/2006/07/10/java_in_notes_domino_explained_domino_session_tester.html
Related
I am calling an agent from an XPage via SSJS:
importPackage(java.net);
importPackage(java.io);
var protocol = context.getUrl().getScheme();
var host = context.getUrl().getHost();
var url = protocol + "://" + host;
var path = env["dir_path"];
var dbName = datasource["db_app_filepath"];
var agentRef = "response?OpenAgent";
var paramName = "custId";
var urlAgent = url + "/" + path + dbName + "/" + agentRef;
var agent:URL = new URL(urlAgent);
var agentConnection:URLConnection = agent.openConnection();
var inputReader:BufferedReader = new BufferedReader(new InputStreamReader(agentConnection.getInputStream()));
var res:String="";
while ((inputLine = inputReader.readLine()) != null) {
res+=inputLine;
}
print("value form agent = " + res);
The agent just returns a simple string:
Option Public
Option Declare
Sub Initialize
Dim session As New NotesSession
Dim creator As String
creator = session.EffectiveUserName
Print "Hello World " + creator
End Sub
But in the print statement in the console I see that the login form is presented.
If I access the agent directly in a browser window I get as example returned:
Hello World CN=§Unrestricted §Signer/OU=System/O=ACME
This is the username which I have set in the Run on behalf of property in the agent.
On the XPage I am already authenticated.
Should I provide the credentials in my call or?
The idea behind the code is that I want to check if the user is not creating double entries for a type of object. The objects (Notes documents) have Readers restriction so user X may not see user Y's entries.
ODA has a method for this purpose and if you use the native server session, it should have access - if the server doesn't have access, you'll have a bigger problem at some point with your application.
Factory.getSession(SessionType.NATIVE).getDatabase(filePath).getView("myView").checkUnique(key, Document)
checkUnique() takes an object of the key(s) in the view to check against uniqueness, and the current document. Obviously if a user re-saves a document, it will be unique in the view, so you don't want to throw an error. Similarly, if the keys can be changed, just performing the check on creation will not prevent uniques.
You do need to provide credentials if you want to call an agent via http(s). You could do this using the https://username:password#restofurl format. Of course that’s a headache to maintain.
Update
Verify what gets stored in the log. A Browser would convert that syntax into a Basic Auth header and a normal URL. In Java you might need to create that header yourself.
/Update
The alternative that might work for you: since your browser is authenticated, use an Ajax call from the browser to trigger the agent.
Try that if sessionAsSigner isn’t the user you want to run with.
Of course: don’t do agents is best. You could have a managed bean that creates its own server.id based session.
I want to use java connect Gerrit REST API, so i find the opensource gerrit-rest-java-client. But i don't know how to query the changes commitMessage.
My simple code is as follows
GerritRestApiFactory gerritRestApiFactory = new GerritRestApiFactory();
GerritAuthData.Basic authData = new GerritAuthData.Basic("Gerrit", "User", "password");
GerritApi gerritApi = gerritRestApiFactory.create(authData);
List<ChangeInfo> changes = gerritApi.changes().query("status:merged").withLimit(1).get();
for (ChangeInfo cc : changes) {
System.out.println("subject:" + cc.subject);
System.out.println("changeId:" + cc.changeId);
System.out.println("commitMessage:");
}
You need to query changes adding the "&o=CURRENT_REVISION" to get commit SHA-1 of the current revision (see more details here). Then you need to use the Get Commit endpoint to finally get the commit message.
I am making an app in java that uses Netsuite's SuiteTalk web services to create a report. I defined a transaction saved search in which I use as a criteria the date and I print in the results the default Transaction columns plus the Department external ID and the sum of the amount. I run the saved search via UI and I get what I am expecting, however, when I try to get the information in my java code I keep getting null results. I have tried the java versions of the following solutions:
C# NetSuite WebServices: Get value from custom field in saved search (ItemSearchAdvanced)
http://www.anyforum.in/question/web-service/netsuite/How-to-get-data-from-saved-search-through-webservice-request/345
However, none of this has worked for me. When I go to the Lists->Search->Saved Searches menu on my Netsuite UI, I am able to see my saved search when I set in the filters "General" and "Transaction". However, I haven't been able to retrieve it's information via API.
This is the code that I use to try to get the saved search data:
public void printReport() throws ExceededUsageLimitFault, UnexpectedErrorFault, InvalidSessionFault, ExceededRecordCountFault, RemoteException, UnsupportedEncodingException, SOAPException{
//METHOD 1: Transaction Search
TransactionSearchAdvanced sr = new TransactionSearchAdvanced();
//"customsearchreport" is the IF of my saved search
sr.setSavedSearchId("customsearchreport");
SearchResult res = _port.search(sr);
System.out.println(res.getTotalRecords());
//METHOD 2: Item search
ItemSearchAdvanced isa = new ItemSearchAdvanced();
isa.setSavedSearchId("customsearchreport");
SearchResult resp = _port.search(isa);
System.out.println(resp.getTotalRecords());
//METHOD 3: General saved search
GetSavedSearchRecord gssr= new GetSavedSearchRecord();
//I set the record type as "transaction" as I created a transaction saved search.
gssr.setSearchType(SearchRecordType.transaction);
GetSavedSearchResult gssre = _port.getSavedSearch(gssr);
System.out.println("Saved Search status: "+ gssre.getStatus().isIsSuccess());
RecordRefList srl = gssre.getRecordRefList();
RecordRef[] rr = srl.getRecordRef();
System.out.println("RecordRef[] size: " + rr.length);
for (int i = 0; i < rr.length; i++) {
RecordRef rref = rr[i];
System.out.println("External ID: " + rref.getExternalId());
System.out.println("Internal ID: "+ rref.getInternalId());
System.out.println("Name: "+ rref.getName());
}
}
With METHODS 1 and 2, I am not able to obtain results (I print "null"). The third method prints me 16 saved searches, however, none of the printed searches correspond to the ones I have created. When I check the saved search list through the UI, I see that there exist 21 non private saved searches and 4 have been created by me. From the 16 reports that are printed, one corresponds to a private saved search.
So, I don't get why I can't get my saved search result and what determines if a report is accessible through any method. Any help to obtain my savedSearch throough the API would be appreciated. Also, could any one explain how Netsuite determines which saved searches appear through any "get" method?
Thanks!
I solved it. The ID "customsearchreport" I was using is a UI ID. I had to use the InternalID for my report. Also, I was able to print my saved search IDs with the getSavedSearch() method by selecting the "All company members" checkbox in my the "Audience" section of my saved search.
I solved them
Before the second script, we must increase the number pages limit like this:
SearchPreferences sp = new SearchPreferences();
sp.pageSize = 1000;
_service.searchPreferences = sp;
SubsidiarySearch subsidiarySrch = new SubsidiarySearch();
SearchResult srchResult = _service.search(subsidiarySrch);
I am very new to xpages. I have been searching the web for an answer to my question for a while now. Seems like the answer should be simple.
I have been playing around with a snippet of code that I got from Brad Balassaitis's excellent Xcellerent.net site that populates a list of "jumptoitems" for a viewpanel dynamically. The code is run from the beforeRenderResponse event of the xpage.
var viewName = getComponent('viewPanel1').getData().getViewName();
var vw = database.getView(viewName);
var colNum = 1;
var cols:Vector = vw.getColumns();
for (var i=0; i < cols.length; i++) {
if (cols[i].isSorted() && !cols[i].isHidden()) {
colNum = i + 1;
break;
}
}
var letters = #DbColumn(null, viewName, colNum);
var options = #Trim(#Unique(#UpperCase(#Left(letters, 1))))
viewScope.put('jumpToOptions', options);
It works beautifully - but I want to modify the code to reference a view in a different database. In the post Brad says that the code can be "enhanced" to accomplish this. But I have been experimenting and searching for a while and cannot accomplish the enhancement.
Thanks for any help.
--Lisa&
In your second line, you establish a handle on the view by viewName you pull from the component viewPanel1. Your call is database.getView(viewName). This amounts to a programmatic reference of NotesDatabase.getView(). If you get a handle on the other database you want to connect to, they you can invoke the same .getView() call on that handle.
First, establish your connection to the other database; this is done via the session keyword (which is a NotesSession), as such:
var extDB = session.getDatabase(dbName)
As Howard points out, that session keyword is the current user's session and will be subject to all ACL rights/assignments/roles as that user. If you need to elevate privileges to programmatically expose additional data, you can do so with the sessionAsSigner keyword (which is also a NotesSession, just with the credentials of the signer, yourself, or you can have the NSF signed as the server ID, to give it even higher privileges).
Then proceed as usual with your extDB handle in place of the database keyword (which is about the same as session.getCurrentDatabase()); like so:
var vw = extDB.getView(viewName)
The NotesDatabase.getView() call will return null if a View by that name doesn't exist in that NSF, so you'll want to ensure that it's there and programmatically check for and handle a null return.
[Edit]
Since you're using the ported # function of #DbColumn as it is, to use the approach as Frantisek Kossuth suggests may be easy, but relies on the NotesSession of the current user. To override that user's (lack of) privileges and get full visibility of all documents' values in the separate NSF, you would still need to get a handle on the columnValues for the View as shown above, using the sessionAsSigner keyword.
[/Edit]
Based on your code you need to specify database in #DbColumn formula, too.
var letters = #DbColumn([database], viewName, colNum);
You can read about it here or there...
Aside of documented formats you can use API format "server!!database" as single string value.
This piece of code moves all current versions of files from one folder to another but leaves all older versions unmoved. (Context is java code of DFC accessing Documentum.)
String strObjId = versionColl.getString("r_object_id");
com.documentum.fc.common.IDfId curObjectID = new DfId(strObjId);
IDfSysObject curObj = (IDfSysObject)sess.getObject(curObjectID);
versionlabel = curObj.getAllRepeatingStrings("r_version_label", ",");
System.out.println("Moving document with Name:" + objName + " and version:" + versionlabel);
if (runMode.equals("1")) {
curObj.unlink(oldpath);
curObj.link(newpath);
curObj.setString("a_special_app", curObj.getString("r_modifier"));
curObj.setTime("a_last_review_date", curObj.getTime("r_modify_date"));
curObj.setString("a_category","MOVED");
curObj.save();
System.out.println("Successfully Moved document with Name:" + objName + " and version:" + versionlabel);
}
The error we were getting while moving older versions was "document immutable". So we added this piece of code that temporarily disables the immutable flag, allows the file to be moved and then resets the immutable flag to true.
curObj.setBoolean("r_immutable_flag", false);
The problem then was that this code ran perfectly on our dev machine (windows) while it crashed on production(windows) (gave link error). Any ideas as to why this is acting as it is and other codes to solve this issue would be great. Thanks.
Based on the little info given, it could be just about anything but my guess is that it's a permissions issue. Specifically, the user running this code does not have the proper permissions to move one(or more) of the documents you are trying to move OR the user running the code does not have enough permissions to link objects to the target folder.