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!

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
PaulCutcliffeAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ADSLMarkCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
PaulCutcliffeAuthor Commented:
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
ADSLMarkCommented:
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
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

PaulCutcliffeAuthor Commented:
But this is a Lotus Domino Agent, so there is no class file or directory.
0
PaulCutcliffeAuthor Commented:
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
ADSLMarkCommented:
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
PaulCutcliffeAuthor Commented:
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
ADSLMarkCommented:
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
PaulCutcliffeAuthor Commented:
Brilliant. Now it's running as an Agent on the Domino server - thanks for your help.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Lotus IBM

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.