logo

Using Java Enumerations With Domino

Recently I found myself writing a Java-based Agent in Domino for the first time in a year or more and found myself doing things I'd not thought possible the last time I did.

Until two or three years ago the extent of my "programming" was that I could write Agents which contained simple where, while and if statements. Inside there I'd be calling some .replaceItemValue() and .save() methods. That was about as complicated as it got.

Things only ever got any more complex than that if I stepped away from LotusScript and in to Java Agents. I'd do this only when I needed to. When I was creating PDFs, Zip files or generating images on the fly. Things got a bit more complicated then but all I'd ever be doing is figuring out how to use an existing API. Again, not what you'd call programming.

I never felt like I did any actual programming until I stepped outside Domino and in to C# and ASP.NET development a few years back. Since using C# and reading a few books I'm starting to gain a better understanding and appreciation of the finer aspects of coding.

One of the things I did in the Domino Java Agent was use as enumeration (enum). As an example let's use one to define the various workflow statuses a Notes document can pass through.

Here's the enum definition:

 private enum WorkflowStatus {
    UNKNOWN("Unknown", "The document hasn't yet entered an approval cycle"),
    IN_PROCESS("Awaiting Approval", "There are still approvers in the loop"),
    APPROVED("Approved", "This document has been approved"),
    DECLINED("Declined", "This document was declined");

    private final String value;
    private final String detail;

    private WorkflowStatus(String value, String detail) {
        this.value = value;
        this.detail = detail;
    }

    public static WorkflowStatus findByValue(String value) {
        if(value != null) {
            for(WorkflowStatus status : values()) {
                if(status.value.equals(value)) {
                    return status;
                }
            }
        }

        return WorkflowStatus.UNKNOWN;
    }

    /**
     * @return the value
     */
    public String getFieldValue() {
        return value;
    }

    /**
     * @return the detail
     */
    public String getDetail() {
        return detail;
    }
 }

You can use it in a WQS Agent's Java code like this:

public class JavaAgent extends AgentBase {
 public void NotesMain() {
    Session session = getSession();
    AgentContext agentContext = session.getAgentContext();
    Database database = session.getCurrentDatabase();
    Document document = agentContext.getDocumentContext();

    WorkflowStatus status = WorkflowStatus.findByValue(
            document.getItemValueString("Status")
        );

    switch (status){
        case IN_PROCESS:
            if (document.getItemValueString("AwaitingApprovalBy").equals("")){
                status = WorkflowStatus.APPROVED;
            }
            break;
        case APPROVED:
            status = WorkflowStatus.DECLINED;
            break;
        case UNKNOWN:
            status = WorkflowStatus.IN_PROCESS;
            break;
    }

    document.replaceItemValue("Status", status.getFieldValue());
 }
}

Obviously this isn't real code (it makes no sense to decline an approved document!). It's just to show how the code can utilise the enum.

You could take this further and store a integer value in the backend document, so that you never actually store a string as the status. If you then need to change the definition of a status it becomes a lot easier.

To a degree I've never known whether avoiding hard-coding is really worth it with Domino? More often than not a document is only ever saved and processed using the same WQS Agent. It's only when there's code in multiple places that something like the above enum becomes worth it.

But still, it's all good practise. Using the code above feels a whole lot better than the alternative of scattering string representations of your statuses all over the code.

Another thing I did in the Java Agent was move all strings to the top of the code (things like messages displayed to the user) and defined them as static constants. This way it's easier for me (and future developers) to come and make quick changes without having to sift through all the code.

Comments

  1. It's entirely possible I've misplaced half my brain today, so bear with me.

    It looks to me like you're using an enum as an object / class. My (perhaps limited) understanding of the reasons for and uses of enums were limited to a list (enumeration) of related bits of information.

    eg

    private enum Connection

    int port = 80;

    int ssl = 443;

    String domain = "codestore.net";

    String uri = "";

    end enum

    Thus providing a convenient container and nothing more. So it's interesting to me that your enum has methods. I suppose there's nothing saying they can't but it seems then an odd choice of pattern over use of a class.

      • avatar
      • Jake Howlett
      • Tue 11 Oct 2011 11:17 AM

      Must be peculiar to Java I guess. I used them a lot in C# but only in a simple way like you example.

      Show the rest of this thread

  2. Been doing a lot of Domino Java work lately, too -- this I learned today: ".equals("")"

    Been using !isEmpty() up until now. :P

    1. See Peter Haggar's commentary on .equals, ==, ===, etc. in Practical Java. Good read on the subject.

    • avatar
    • Wayne Sobers
    • Tue 11 Oct 2011 06:06 PM

    shouldn't "return TransactionStatus.UNKNOWN;"

    be "return WorkflowStatus.UNKNOWN;" ?

      • avatar
      • Jake Howlett
      • Wed 12 Oct 2011 02:14 AM

      Woops. Yeah, you're right. That's what happens when you re-write code in a text editor. Will fix now.

  3. oops,

    shouldn't "return TransactionStatus.UNKNOWN;"

    be "return status.UNKNOWN;" ?

    I find the in line definition of variables in Java to be somewhat off putting..

      • avatar
      • Jake Howlett
      • Wed 12 Oct 2011 02:15 AM

      Nope. You were right first time.

  4. I've used the blessings of Java in Domino development for quite a while. About two years ago we faced a complex requirement we had to implement a solution for. The attempted approach cried for a event broker / event bus implementation which is truly a pain in the .... to implement in LotusScript.

    So we switched to Java and used Reflection to register any objects that need to be notified whenever an event is posted on the broker / bus. Always remember, however, to alter the java.policy file on the server to enable use of Reflection.

    The coupling of Formula / LotusScript frontend - Java Backend was kind of quirky at first, but when we got Webservice Providers and Consumers within Lotus Domino it worked like a charm implementing the Java (server) side as provider and the LotusScript (client) end as consumer. This way the bridge between the two languages is provided by Notes/Domino. Works very well.

    Ever since this experience I try to implement as much as I can in Java, it's just so much easier and direct to work with. The only thing I don't like at all is having to recycle every single Domino object you created in order to avoid memory leaking.

      • avatar
      • Aaron Hardin
      • Fri 14 Oct 2011 12:09 PM

      Recycling in java is always required though right, not just in Domino?

      Hide the rest of this thread

      1. Well, in Java there is a garbage collector active that usually removes objects in memory that are no longer referenced. Domino only needs the recycling because Java within Domino in truth is just a thin layer on actual C++ objects. The Java part is cleaned up by the garbage collection, however the underlying C++ objects never know, when they're no longer needed. The recycle() method basically tells them to free up the space they used in memory. So as long as you're using pure Java, there is no recycling needed.

        The lack of a destructor within Java can also be a challenge if you want to make sure that objects are unloaded in a certain way. There is no real way of telling when the garbage collector exactly hits the objects and in what order, at least to my knowledge.

      2. What Gernot said is correct. The recycle() method is peculiar to Domino and is not part of Java.

        To expand a bit, I think Domino calls recycle() automatically when an agent exits. So if you're not looping in the code you likely don't have to worry about it.

        But if you are looping within the Java code and creating objects on each loop, each of which is going to consume memory, then you may consume all available memory before the agent exits.

        This has happened to me when processing many documents from a view. For instance I've written agents to make one-time changes to tens of thousands of documents when adding new features or fixing a bug.

        In those cases I have to call recycle() on each document object once it's saved or the agent will crash before finishing all the documents.

        As a result, I try to add the recycle() call in all the code I write in case it might end up being reused in just such a situation.

Your Comments

Name:
E-mail:
(optional)
Website:
(optional)
Comment:


About This Page

Written by Jake Howlett on Tue 11 Oct 2011

Share This Page

# ( ) '

Comments

The most recent comments added:

Skip to the comments or add your own.

You can subscribe to an individual RSS feed of comments on this entry.

Let's Get Social


About This Website

CodeStore is all about web development. Concentrating on Lotus Domino, ASP.NET, Flex, SharePoint and all things internet.

Your host is Jake Howlett who runs his own web development company called Rockall Design and is always on the lookout for new and interesting work to do.

You can find me on Twitter and on Linked In.

Read more about this site »

More Content