Solved

Please help me to convert my Java Application so it can run as a Lotus Domino Java Agent - before I pull all my hair out!

Posted on 2007-03-31
9
885 Views
Last Modified: 2013-12-18
Firstly let me explain that although an experienced programmer/developer, my experience of Java is very limited (more's the pity - what a fantastic language!), so what would probably be quite straightforward otherwise is actually very frustrating!

I have developed a Java Application that uses DIIOP to connect to a Lotus Domino server to do various things. It was designed as a Java Application, because at the time, there was no local Domino server; however, now there is, I would like to move the code into a Domino Agent, so it can run from inside the database, avoid connectivity issues & not have to be scheduled to run on a user's computer.

However, I am having trouble getting any of it to work from within an Agent. Not only am I have the context issues I was expecting (i.e. different main class & starting point) but I am even having trouble getting simple functions to work, e.g. String strLogFileName = String.format("%1$tY%1$tm%1$td-%1$tH%1$tM%1$tS", cal);

One other thing that may not be helping. When installing NetBeans IDE 5.0 (which I used to develop the application), for some reason I selected the then beta Java JDK 1.6. Consequently, when I installed the Application on the user's PC, I had to install the JRE 1.6 too, which is fair enough. I'm running Lotus Domino R7.0.1, which I guess only has JRE 1.5 - could this be adding to my problems?

Here's the code of my orginal Java Applpication:

package sourcedownloader;

import lotus.domino.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.text.NumberFormat;

public class Main {
   
    public Main() {
    }
   
    public static void main(String[] args) {
        try {
            System.out.println("DownloadSourceMaterials Running.");
            File file;
            HttpURLConnection httpConnection;
            String strFilename;
            String strOrderNo;
            Calendar cal = Calendar.getInstance();
            Document docOrder;
            DocumentCollection dcOrderItems;
            Document docOrderItem;
            String strOrderItemsStatus;
            String strLogFileName = String.format("%1$tY%1$tm%1$td-%1$tH%1$tM%1$tS", cal);
            Session session = NotesFactory.createSession("hostname.domain.local", "Username/Organisation", "password");
            Database dbThis = session.getDatabase("", "Database.nsf");
            Document docSettings = dbThis.getProfileDocument("Settings", "");
            String strDownloadsFolder = docSettings.getItemValueString("DownloadsFolder");
            String strCredentials = docSettings.getItemValueString("DownloadsUsername") + ":" + docSettings.getItemValueString("DownloadsPassword");
            String strCredentialsEncoded = new sun.misc.BASE64Encoder().encode(strCredentials.getBytes());
            file = new File(strDownloadsFolder + "Logs");
            if(! file.exists()) {
                System.out.println("Logs Folder '" + strDownloadsFolder + "Logs' not found - creating...");
                file.mkdirs();
            }
            FileOutputStream logger= new FileOutputStream(strDownloadsFolder + "Logs\\" + strLogFileName + ".log");
            PrintStream logStream = new PrintStream(logger);
            System.setOut(logStream);
            System.setErr(logStream);
            System.out.println("DownloadSourceMaterials Running...");
            View viewDownloads = dbThis.getView("(SourceDownloads)");
            viewDownloads.setAutoUpdate(false);
            Document docDownload = viewDownloads.getFirstDocument();
            while (null != docDownload) {
                System.out.println("Found Download for " + docDownload.getItemValueString("DescriptiveName") +"...");
                strOrderNo = docDownload.getItemValueString("OrderNo");
                file = new File(strDownloadsFolder + strOrderNo);
                if(! file.exists()) {
                    System.out.println("Destination Folder '" + strDownloadsFolder + strOrderNo + "' not found - creating...");
                    file.mkdirs();
                }
                docDownload.replaceItemValue("SourceDownload", "2");
                docDownload.save(true);
                URL urlSource = new URL(docDownload.getItemValueString("SourceFileDownloadURL"));
                strFilename = urlSource.toString().substring(urlSource.toString().lastIndexOf("/") + 1);
                System.out.println("Attempting to download material from '" + urlSource.toString() + " to '" + strDownloadsFolder + strOrderNo + "\\" + strFilename + "' using Credentials '" + strCredentials + "'...");
                httpConnection = null;
                httpConnection = (HttpURLConnection) urlSource.openConnection();
                httpConnection.setRequestProperty("Authorization", "Basic " + strCredentialsEncoded);
                httpConnection.setRequestMethod("GET");
                httpConnection.setUseCaches(false);
                httpConnection.connect();
                System.out.println("File size: " + NumberFormat.getInstance().format(httpConnection.getContentLength()) + " bytes.");
                InputStream inputStream = httpConnection.getInputStream();
                int code = httpConnection.getResponseCode();
                if (code == HttpURLConnection.HTTP_OK) {
                    byte[] buffer = new byte[4096]; //create a 4k buffer
                    File fileOutput = new File(strDownloadsFolder + strOrderNo + "\\" + strFilename);
                    FileOutputStream outputStream= new FileOutputStream(fileOutput);
                    int bytes = 0;
                    int bytesRemaining = httpConnection.getContentLength();
                    while (bytesRemaining > 0) {
                        bytes = inputStream.read(buffer);
                        outputStream.write(buffer, 0, bytes);
                        bytesRemaining -= bytes;
                    }
                    outputStream.close();
                }
                httpConnection.disconnect();
                docDownload.replaceItemValue("SourceDownload", "3");
                docDownload.save(true);
                strOrderItemsStatus = "";
                docOrder = dbThis.getDocumentByUNID(docDownload.getParentDocumentUNID());
                dcOrderItems = docOrder.getResponses();
                docOrderItem = dcOrderItems.getFirstDocument();
                while (null != docOrderItem) {
                    strOrderItemsStatus += docOrderItem.getItemValueString("SourceDownload");
                    docOrderItem = dcOrderItems.getNextDocument(docOrderItem);
                }
                if (strOrderItemsStatus.contains("E")) {
                    docOrder.replaceItemValue("DownloadsStatus", "E");
                } else if (strOrderItemsStatus.contains("1")) {
                    docOrder.replaceItemValue("DownloadsStatus", "0");
                } else {
                    docOrder.replaceItemValue("DownloadsStatus", "1");
                }
                docOrder.save(true);
                docDownload = viewDownloads.getNextDocument(docDownload);
            }
        } catch(Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("DownloadSourceMaterials completed.");
        }
    }
}

And here is my attempt to make this code into an Agent:

import lotus.domino.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.text.NumberFormat;

public class JavaAgent extends AgentBase {

      public void NotesMain() {

            try {
                  Session session = getSession();
                  AgentContext agentContext = session.getAgentContext();
                  

                  System.out.println("DownloadSourceMaterials Running...");
                  File file;
                  HttpURLConnection httpConnection;
                  String strFilename;
                  String strOrderNo;
                  Calendar cal = Calendar.getInstance();
                  Document docOrder;
                  DocumentCollection dcOrderItems;
                  Document docOrderItem;
                  String strOrderItemsStatus;
                  String strLogFileName = String.format("%1$tY%1$tm%1$td-%1$tH%1$tM%1$tS", cal);
                  Database dbThis = agentContext.getCurrentDatabase();
                  Document docSettings = dbThis.getProfileDocument("Settings", "");
                  String strDownloadsFolder = docSettings.getItemValueString("DownloadsFolder");
                  String strCredentials = docSettings.getItemValueString("DownloadsUsername") + ":" + docSettings.getItemValueString("DownloadsPassword");
                  String strCredentialsEncoded = new sun.misc.BASE64Encoder().encode(strCredentials.getBytes());
                  file = new File(strDownloadsFolder + "Logs");
                  if(! file.exists()) {
                      System.out.println("Logs Folder '" + strDownloadsFolder + "Logs' not found - creating...");
                      file.mkdirs();
                  }
                  FileOutputStream logger= new FileOutputStream(strDownloadsFolder + "Logs\\" + strLogFileName + ".log");
                  PrintStream logStream = new PrintStream(logger);
                  System.setOut(logStream);
                  System.setErr(logStream);
                  System.out.println("DownloadSourceMaterials Running...");
                  View viewDownloads = dbThis.getView("(SourceDownloads)");
                  viewDownloads.setAutoUpdate(false);
                  Document docDownload = viewDownloads.getFirstDocument();
                  while (null != docDownload) {
                      System.out.println("Found Download for " + docDownload.getItemValueString("DescriptiveName") +"...");
                      strOrderNo = docDownload.getItemValueString("OrderNo");
                      file = new File(strDownloadsFolder + strOrderNo);
                      if(! file.exists()) {
                          System.out.println("Destination Folder '" + strDownloadsFolder + strOrderNo + "' not found - creating...");
                          file.mkdirs();
                      }
                      docDownload.replaceItemValue("SourceDownload", "2");
                      docDownload.save(true);
                      URL urlSource = new URL(docDownload.getItemValueString("DescriptiveName"));
                      strFilename = urlSource.toString().substring(urlSource.toString().lastIndexOf("/") + 1);
                      System.out.println("Attempting to download material from '" + urlSource.toString() + " to '" + strDownloadsFolder + strOrderNo + "\\" + strFilename + "' using Credentials '" + strCredentials + "'...");
                      httpConnection = null;
                      httpConnection = (HttpURLConnection) urlSource.openConnection();
                      httpConnection.setRequestProperty("Authorization", "Basic " + strCredentialsEncoded);
                      httpConnection.setRequestMethod("GET");
                      httpConnection.setUseCaches(false);
                      httpConnection.connect();
                      System.out.println("File size: " + NumberFormat.getInstance().format(httpConnection.getContentLength()) + " bytes.");
                      InputStream inputStream = httpConnection.getInputStream();
                      int code = httpConnection.getResponseCode();
                      if (code == HttpURLConnection.HTTP_OK) {
                          byte[] buffer = new byte[4096]; //create a 4k buffer
                          File fileOutput = new File(strDownloadsFolder + strOrderNo + "\\" + strFilename);
                          FileOutputStream outputStream= new FileOutputStream(fileOutput);
                          int bytes = 0;
                          int bytesRemaining = httpConnection.getContentLength();
                          while (bytesRemaining > 0) {
                                    bytes = inputStream.read(buffer);
                                    outputStream.write(buffer, 0, bytes);
                                    bytesRemaining -= bytes;
                          }
                          outputStream.close();
                      }
                      httpConnection.disconnect();
                      docDownload.replaceItemValue("SourceDownload", "3");
                      docDownload.save(true);
                      strOrderItemsStatus = "";
                      docOrder = dbThis.getDocumentByUNID(docDownload.getParentDocumentUNID());
                      dcOrderItems = docOrder.getResponses();
                      docOrderItem = dcOrderItems.getFirstDocument();
                      while (null != docOrderItem) {
                          strOrderItemsStatus += docOrderItem.getItemValueString("SourceDownload");
                          docOrderItem = dcOrderItems.getNextDocument(docOrderItem);
                      }
                      if (strOrderItemsStatus.contains("E")) {
                          docOrder.replaceItemValue("DownloadsStatus", "E");
                      } else if (strOrderItemsStatus.contains("1")) {
                          docOrder.replaceItemValue("DownloadsStatus", "0");
                      } else {
                          docOrder.replaceItemValue("DownloadsStatus", "1");
                      }
                      docOrder.save(true);
                      docDownload = viewDownloads.getNextDocument(docDownload);
            }
        } catch(Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("DownloadSourceMaterials completed.");
        }
    }    
}

When I try to save the Agent, I get the following errors:

sourcedownloader\JavaAgent.java:26: cannot resolve symbol
symbol : method format (java.lang.String,java.util.Calendar)
location: class java.lang.String
          String strLogFileName = String.format("%1$tY%1$tm%1$td-%1$tH%1$tM%1$tS", cal);
                                  ^

sourcedownloader\JavaAgent.java:93: cannot resolve symbol
symbol : method contains (java.lang.String)
location: class java.lang.String
          if (strOrderItemsStatus.contains("E")) {
                                ^

sourcedownloader\JavaAgent.java:95: cannot resolve symbol
symbol : method contains (java.lang.String)
location: class java.lang.String
          } else if (strOrderItemsStatus.contains("1")) {
                                     ^

3 errors

By the way, isn't the Domino Designer Java Agent IDE a delight to use? Especially after using Visual Studio & NetBeans IDE!

So please could someone help me work through my various issues here? I appreciate there are probably a number of different issues, hence the points available.

Thanks in advance,
Paul Cutcliffe
0
Comment
Question by:PaulCutcliffe
  • 5
  • 4
9 Comments
 
LVL 10

Accepted Solution

by:
ADSLMark earned 500 total points
ID: 18828772
String.format() and String.contains() were added in version 1.5.. I guess that's were your problem lies. You can easily replace these two methods with a custom method I guess. For the contain() you can also use public int indexOf(String), returns -1 if the string does not contain the parameter.
For the other method you probably have to call the appropriate methods on the call object yourself and then build the string.

Mark
0
 

Author Comment

by:PaulCutcliffe
ID: 18828859
Aha, so Notes/Domino R7.0.1 must have an even older JRE in? That explains the errors then. I can't seem to find anywhere the version of the JRE shipped with Domino R7.0.1, but I have managed to find that R7.0.2 ships with Java Development Kit (JDK) 1.4.2 SR4, so it must be the same or earlier.

However, if I comment out these lines, it then complains as follows:

Error loading Agent Class: lulusourcedownloader.JavaAgent
java.lang.ClassNotFoundException: lulusourcedownloader.JavaAgent
      at lotus.domino.AgentLoader.loadClass(Unknown Source)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:494)
      at lotus.domino.AgentLoader.runAgent(Unknown Source)

Is that something to do with the new context as a Notes Agent, rather than as an application? Is that something you can help me with too?

Thanks.
0
 
LVL 10

Expert Comment

by:ADSLMark
ID: 18828882
Looks like your JavaAgent is in the wrong place. The error message says all, it cannot find your class, while trying to load the agent. I think because of the packaging you have to place the class file in a directory "lulusourcedownloader". This is the most common mistake when encountering this exception.

So the structure should like something like:
<base dir>/lulusourcedownloader/JavaAgent.class

Mark
0
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

Author Comment

by:PaulCutcliffe
ID: 18829027
But this is a Lotus Domino Agent, so there is no class file or directory.
0
 

Author Comment

by:PaulCutcliffe
ID: 18829049
Although I've just noticed that within the Agent in Domino Designer, in the left hand pane, it says the following:

lulusourcedownloader/JavaAgent.java
__JavaAgent
____NotesMain()

Does this mean that Domino is pretending it is in a directory called lulusourcedownloader?

You'll have to forgive me, but I have very little knowledge of how these Java Agents work within the context of a Domino Database Agent.
0
 
LVL 10

Expert Comment

by:ADSLMark
ID: 18829055
Ehh? Well i have no experience with Lotus Domino Agent, I just know that a classnotfoundexception is thrown whenever a class could not be found. This can have multiple reasons:
- the class didn't compile correctly and therefore doesn't exist
- the class is in the wrong place (because of directory structure or sth)
- the classpath does not contain the correct search path and therefore it cannot find the base directory or class file
- the names are incorrect and therefore a class with a different name should be used.
0
 

Author Comment

by:PaulCutcliffe
ID: 18829505
I see, so something within the Lotus Domino environment that equates to the directory structure is not configured properly.

Aha, I think I've sussed it! For some reason, that path was built in to the Class name, but I've created a new Agent, & then a new class, & it doesn't have the path in, & so compiles, although now I get this error on running:

DownloadSourceMaterials Running...
java.security.AccessControlException: access denied (java.lang.RuntimePermission setIO)
      at java.security.AccessControlContext.checkPermission(AccessControlContext.java:292)
      at java.security.AccessController.checkPermission(AccessController.java:476)
      at java.lang.SecurityManager.checkPermission(SecurityManager.java:538)
      at COM.ibm.JEmpower.applet.AppletSecurity.superDotCheckPermission(AppletSecurity.java:1422)
      at COM.ibm.JEmpower.applet.AppletSecurity.checkRuntimePermission(AppletSecurity.java:1284)
      at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1498)
      at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1437)
      at java.lang.System.checkIO(System.java:223)
      at java.lang.System.setOut(System.java:187)
      at JavaAgent.NotesMain(JavaAgent.java:40)
      at lotus.domino.AgentBase.runNotes(Unknown Source)
      at lotus.domino.NotesThread.run(Unknown Source)
DownloadSourceMaterials completed.
0
 
LVL 10

Expert Comment

by:ADSLMark
ID: 18829553
Heh, yeah.. java and its permissions.. well you need to make a policy file.. take a look at the following website:

http://java.sun.com/j2se/1.4.2/docs/guide/security/permissions.html

It describes the security details of java.. and the following describes the policy file syntax:

http://java.sun.com/j2se/1.4.2/docs/guide/security/PolicyFiles.html

Mark
0
 

Author Comment

by:PaulCutcliffe
ID: 18839587
Brilliant. Now it's running as an Agent on the Domino server - thanks for your help.
0

Featured Post

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
ejb stateless example 2 18
String array comparison 4 38
Java: The Public Class Main 4 30
Java class and jar 3 20
Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Problem "Can you help me recover my changes?  I double-clicked the attachment, made changes, and then hit Save before closing it.  But when I try to re-open it, my changes are missing!"    Solution This solution opens the Outlook Secure Temp Fold…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

808 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question