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
869 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
 

Author Comment

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

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 

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

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

This article covers general Notes 8.5 troubleshooting information including recreating the Notes\Data folder.
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.

743 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now