Utilities

Copying design elements via script in #XPages

One of my first posts was about copying a view from one database to many using XPages. Well, as I was surfing the help documents to learn more about FTSearch in order to extend the capabilities of my Excel exporting capabilty, I found createNoteCollection.

createNoteCollection can be used to create a collection of all notes in a Notes database. That is, not just Notes documents, but all Notes design elements. Not only that, but you can quickly choose what kind of notes you want in your note collection. While there are boolean parameters for each type of note you might want, I am most intrigued by the combination ones, which allow you to select by category.

selectAllAdminNotes (ACL and replication formulas)
selectAllCodeElements (agents, database script, outlines, script libaries and misc code elemnts)
selectAllDataNotes (documents AND profile documents)
selectAllDesignElements (code, format, index, help, icons and shared fields)
selectAllFormatElements (actions, forms, framesets, image resources, java resources, misc format elements, pages, style sheets and subforms)
selectAllIndexElements (folders, misc index elements, navigators and views)
selectAllNotes (everything)

So, once you create  your note collection, then you can walk the collection using getFirstNoteID and getNextNoteID, accessing each design element (or document). Then, using NotesDatabase.getDocumentByID to get a handle to it as a NotesDocument, so you can use NotesDocument.CopyToDatabase to copy the design element across to the new database.

var db:NotesDatabase=database;
var notecollection:NotesNoteCollection=db.createNoteCollection();
notecollection.selectAllDesignElements();
var noteID:String=notecollection.getFirstNoteID();
var note:NotesDocument;
var nextNote:NotesDocument;
while ( noteID != null ) {
	note=db.getDocumentByID(noteID);
	if ( note != null ) {
		note.copyToDatabase();
	}
	noteID=notecollection.getNextNoteID();
	nextNote=db.getDocumentByID(noteID);
	note.recycle();
	nextNote=note;
}

Now, it is a little blunt to grab all design elements and copy them from one database to another. One problem is that you are certain to have some duplication of design elements and I’m sure that will create problems. I know that I was able to have two identically named views in my original post, so I didn’t copy the view if it already existed in the destination database. So, you might want to create collections in both databases and compare the design notes t0o make sure not to create duplicates (either by deleting the one in the destination database first or simply not copying the new one in).

Advertisement
Categories: Old Notes, Server-Side Javascript, Utilities, Xpages | Tags: , , | Leave a comment

Java still not refreshing correctly in #XPages 8.5.3 UP 1

You know, I had started on a post on the great power of comparing design elements, but all I’d written so far was:

With the move to an Eclipse-based Domino Designer Environment, there was at least one significant improvement – the native ability to compare design elements.

I was a big fan of TeamStudio‘s Delta, since I often needed to compare versions of my designs either to document the changes I’d made or, in rare circumstances, do a little troubleshooting to see where I’d accidentally screwed up my designs. It was a great tool, with a lot of smarts about how to report on the designs and it even allowed you to compare documents. They have, of course, updated Delta to provide more capability than is native in Notes – allowing graphical display of design differences rather than just code variances. That said, I don’t have a current license, so I’m using the native tools.

In one of my hotter posts, I’d noted that Java is not behaving well in my environment. The basic behavior is that I’d make changes to my template, do a build and then, when I refreshed the design on the server, things would not refresh properly in Java. In the last few days, the behavior has become very consistent. For some reason, it plagues Mark Leusink‘s DebugToolbar, which is an excellent tool that works fine when my environment behaves.

Basically, the end-user experience of the problem was that, every once in a while, without code changes to the DebugToolbar, I’d start getting Error 500’s that it could not find that class. So, I started to get in the habit of checking in the WebContent/WEB-INF/classes folders using the Navigator view in my designer client to see if the classes were all there.

When builds worked, it would create the DebugToolbar and Message classes, plus the three private classes within DebugToolbar (FieldComparable, FileInfo and MethodComparable). When things didn’t work, sometimes it wouldn’t create the two main classes. Refreshing the design on the server again would never repair it. It would often create 2 or 3 additional copies of each of the private classes, appending what looks like a UNID to the class name. Those tend to have file sizes like -1kb.

Bad Class List

This started in August, as I was making changes to some other Java files. I never changed DebugToolbar, but it would often get corrupted. It settled down as my Java changes ended. I went on vacation for two weeks (Avignon!) and returned to a stable environment. Of course, no one had touched the Java while I was gone and I saw no need until a few weeks ago to make any changes myself.

Now, I had also updated to v3.01 of the DebugToolbar and moved all my Java files into Code/Java from the WebContent/WEB-INF/src folder so that access to them was simpler. However, having been back and forth between versions and back and forth with where the code was stored, I think I can eliminate those as independent problem sources.

Nonetheless, I can consistently see the extra classes and error 500s every time I refresh the design. Deleting the bad classes doesn’t solve anything. Replacing all the class files with the ones from the template also doesn’t work.

If I build the database on the server, the problem goes away.

I’ve been getting frustrated. This might work for me if I’m the only one who makes changes, since the Bethesda server is always a few short hops from me. However, as I may have mentioned before, I work for a very global-oriented company and sometimes our developers are out at project sites where connectivity is slow on good days. Quite frankly, doing a build on the Bethesda server while sitting in Jalalabad is never going to finish in an acceptable time frame. One can build a local template quickly and refresh design far faster.

Fortunately, today I got a new clue.dojo complaint

I started to wonder about corrupt files or problems with the server. So, I created a completely blank file and applied my template (which showed the 5 class files, named normally) to that file. The class files get all corrupted. So, I created a blank file and built as a template from my template. It got corrupt files and also didn’t work as template after building (the same result in the class files). Then, I decided to copy over design elements ad paste them into a blank file. I did a build and got some errors because I’d forgotten to copy over all the libraries and other files hidden under WEB-INF. So, I decided to compare the two databases so I could see what I needed to copy still. Then, I looked at the Java files produced by the XPage builds, just it showed up in the differences between the files and I was shocked. The design on the one I was ‘creating from scratch’ showed all kinds of old versions.

In each of the ‘old’ builds, the Java file created for the XPage would have super(“8.5.3”); but, as shown above, my cut-and-paste built ones would have various complaints, naming other versions and usually with a comment on why. The different line displayed would usually be one of the following:

super("3.0");

super("8.5.2"); // version of xp:view dojoForm

super("8.5.2"); // version of xp:eventHandler disableValidators

super("8.5.1"); // version of xp:eventHandler script

I’d never have noticed if I wasn’t using Compare To Each Other. Now, I need to reinstall Notes and see if the problem goes away or continues. I had Ariwan try and it only worked once for him – and I had to rebuild it on the server – so my hopes are not real high. Since Eric Tomenga has submitted a PMR on the issue, we’re hoping some IBM minds add to my few readers in trying to puzzle out why this is happening.

 

Categories: IDE, Java, Utilities, Xpages | Tags: , , , , , , , , , | 3 Comments

Multi-value Sorting in #Java

I’ve been working on trying to figure out how to sorting Notes views on-the-fly as we’re exporting to Excel and my first thought was, “Oh, that will be in the POI documentation.” I assumed that there would be a simple function in the Apache POI documentation for XSSF to sort rows and that it would also allow us to do multiple column sorts, just like we can manually in Excel. Apparently, doing this is not high on the POI team’s list of tasks.

So, after coming up dry on POI, then on Stack Overflow, I decided to check the interwebs to see what I could find. Sorting collections in Java is actually not all that hard. There are built-in functions for it, so all you have to do is issue a Collections.sort(myObject). Where it gets interesting is in how you compare the objects in the collection.

In order to determine order within the collection, all you have to do is create an integer function within the class named compareTo. Then, it will sort them based on the result returned (comparing one object at to another, not jumping six or seven places at once). So, it you want to sort on multiple values, you return them in reverse order of significance. For example, if I want to sort based on Department, then roll number, then name, I would use the following code:

if ( alphaDepartment == 0 ) {
	if ( rolldifference == 0 ) {
		return alphaName;
	}
	return rolldifference;
}
return alphaDepartment;

When the Department does not match, we return the Department order. If Department matches, we check roll number, returning the difference if it does not match. Finally, if both Department and roll number matched, we return the name order. The bulk of the work is in setting up your compareTo. While this one is hard-coded, I’m sure we’ll be able to figure out how to use variables to identify which value we want to use in our own sorting.

(I’ve dispensed with listing the setters, as they are not needed in this example.)
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@SuppressWarnings({ "unchecked" })
public class Student implements Comparable {

	private String name;
	private String rollNumber;
	private String department;

	// Constructor for the class
	public Student(String name,String rollNumber,String department){
		this.name = name;
		this.rollNumber = rollNumber;
		this.department = department;
	}
	public String toString() {
		return name + ", " + rollNumber + ", " + department;
	}
	public String getName() {
		return this.name;
	}
	public String getRollNumber() {
		return rollNumber;
	}
	public String getDepartment() {
		return this.department;
	}

	//This Function is responsible for sorting.
	public int compareTo(Object student1) {
		if (!(student1 instanceof Student))
			throw new ClassCastException("A Student object expected.");

		Student studentInput = (Student) student1;
		String thisname = this.getName();
		String thatname = studentInput.getName();
		int alphaName = thisname.compareTo(thatname);

		int rollNumb = Integer.parseInt(studentInput.getRollNumber());
		int hostObjrollNumb = Integer.parseInt(this.getRollNumber());
		int rolldifference = hostObjrollNumb - rollNumb;

		String thisDepartment = this.getDepartment();
		String thatDepartment = studentInput.getDepartment();
		int alphaDepartment = thisDepartment.compareTo(thatDepartment);

		if ( alphaDepartment == 0 ) {
			if ( rolldifference == 0 ) {
				return alphaName;
			}
			return rolldifference;
		}
		return alphaDepartment;
	}

	public static void main(String[] args) {
		List<Student> studentList = new ArrayList<Student>();

		//Create our Student objects
		Student s1 = new Student("Tom","3","CS");
		Student s2 = new Student("Jerry","1","Electronics");
		Student s3 = new Student("Merry","4","IT");
		Student s4 = new Student("Tom","2","IT");
		Student s5 = new Student("Jerry","5","IT");
		Student s6 = new Student("Merry","6","Electronics");
		Student s7 = new Student("Tom","1","CS");
		Student s8 = new Student("Jerry","2","IT");
		Student s9 = new Student("Merry","3","Electronics");

		//Add Students to our ArrayList

		studentList.add(s1);
		studentList.add(s2);
		studentList.add(s3);
		studentList.add(s4);
		studentList.add(s5);
		studentList.add(s6);
		studentList.add(s7);
		studentList.add(s8);
		studentList.add(s9);

		//The actual sort command
		Collections.sort(studentList);

		System.out.println("\nThe student list in ascending sequence is:\n");
		for (Student person : studentList) {
			System.out.println(person);
		}
	}
}

As you can see, I included the data in the Java code, since I’m trying to keep it simple. When we move forward to trying this with either the Excel sheet we’ve produced or the data before we export it to Excel, things will be more complicated. Nonetheless, I am enthused about the start I’ve made here.

There are few places that were key in helping me understand this AND from which I borrowed much of the code. On Stack Overflow, there was a question about sorting a multi-dimensional array that got me started (I’ve submitted a correction to the OP’s self-answer, since his self-answer doesn’t actually work.) While that taught me some things, none of that code appeared here. The Student object and my first exposure to how compareTo functioned came in a post on sorting a list in ascending order in Java. Other pages had mentioned compareTo, but it made more sense when I saw it there. The final, clear understanding came with sorting a collection containing user-defined objects, which thankfully also made clear to me how to loop the output properly.

Categories: Java, Utilities | Tags: , , , , , , | 2 Comments

Puzzling behaviour of Java class files in design refreshes in #xpages

This is not a post in which I’m able to dispense some knowledge I’ve gained, but, rather, one in which I share my befuddlement by some of the new things I’m dealing with in XPages.

We have a database suite originally designed for us by Scott Good, Henry Newberry and the good folks at Teamwork Solutions. It’s based off their brilliant Process It! workflow Notes solution. In the original design, they used version 1.3 of Mark Leusink’s Debug Toolbar. Since version 3.01 is now available on OpenNTF, I decided to upgrade. One of the advantages of the upgrade is that now the code resides in Code/Java, accessible more directly from the Designer client than it was when it had to be stored in WebContent/WEB-INF/src. For me, this is far more convenient, since I can see more properties directly (especially about prohibiting design refresh).

Nonetheless, I seem to be having troubles.

I updated the design, then did a clean and a build on my template. Then, I refreshed design on the server copy from the template. At first, it seemed like it wouldn’t bring the built .class files over to the server copy from my template. Now, when I do a design refresh, it “horks” the five files, reducing them all to -1 bytes. If I do a clean & build on the server copy, the files get their expected size.

I believe my classpath is correct, as it builds them properly when I tell it to build in either the template or on the server.

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="Local"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="WebContent/WEB-INF/classes"/>
<classpathentry kind="src" path="Code/Java"/>
</classpath>

In the ACL, this ID has Manager rights, including for creating LotusScript and Java agents. I’ve signed all the files in Code/Java with this ID. I build it with this ID. I conduct the design refresh with the same ID and those same rights.

Does anyone have any ideas what I might be doing wrong that’s inhibiting the class files from refreshing with the rest of the design?

There are two Stack Overflow questions that deal with this directly:

Class files not being created after refresh from template?

XPages Java corruption issue

One of my co-workers did open the design to check the binding for one field, which must have corrupted the files once. That doesn’t explain all the instances, but it helps. This straddles the line between a reason to use templates (so no one even glances at the design in production) and reason not to use templates (because it’s forced me to do builds on production since template changes only produce corrupt class files). Interestingly, it’s only the Debug Toolbar class files that have the problem – the Teamwork Solution ones haven’t corrupted.

Update: It gets worse. I tried building on the local replica so that I could do it quickly, then replicate the class files up to the server. No luck. It overwrites the local files with the corrupted ones from the server.

Categories: IDE, Java, Utilities, Xpages | Tags: , , , , , , | 3 Comments

Copying views from one database to many

Recently, one of our internal clients asked if we could change who could see a button on one view that is in many of our databases. That sounds pretty easy, right? All you have to do is change the template and those changes will be pushed by the Designer task into every database.

Well, unfortunately, while almost all of the 65 databases in question contain the same view, some of those views don’t link back to any template.

I’d learned a while ago that the old Notes.Net forum was no longer particularly active and that the community had decided to move questions to Stack Overflow.

To digress for a moment, Stack Overflow is part of the Stack Exchange “network of communities” and it’s a great place to both seek and provide answers with experts and budding experts. It was founded in 2010 by one of my favorites in the industry, Joel Spolsky, and Jeff Atwood. Joel’s blog, Joel on Software, provided me with a lot of insights into programming, running a business, dealing with people and, oddly enough, with the first news I had of trouble on the morning of 9/11.

So, if you have a Notes, XPages or other problem, go there and ask. I asked around on Stack Overflow (link) and got a recommendation on how to deal with it. Actually, I got a couple of ideas to choose from and Panu Haaramo’s idea was the best. Basically, get a handle to the view by it’s UNID and copy it to the destination database using XPages.

I put a combobox (fileChoices) on the page to allow the user to select which database to push to, hardcoding in the view name, but it could easily be generalized and looped.

// get a handle to this database
var thisdb:NotesDatabase = session.getCurrentDatabase();
// get server
var server = "MyServer/MyCompany";
// get filepath
var filepath = getComponent("fileChoices").getValue();
getComponent("status").setValue("Searching for "+filepath);
// get a handle to the destination database 
var dbTarget:NotesDatabase = session.getDatabase(server,filepath);
// delete the Manuals view
var oldView:NotesView = dbTarget.getView("Manuals");
if ( @IsNull (oldView) ) { getComponent("status").setValue("Null"); 
} else {
    getComponent("status").setValue(getComponent("status").getValue()+", Trying "+ dbTarget.getTitle());
    try { oldView.remove();
        // get a handle to this Manuals view
        // copy the view to the destination database
        thisdb.getDocumentByUNID(thisdb.getView("Manuals").getUniversalID()).copyToDatabase(dbTarget);
        getComponent("status").setValue(getComponent("status").getValue()+", Updated on "+filepath);
    }
    catch (ex) {
        getComponent("status").setValue(getComponent("status").getValue()+", No update for "+filepath);
    };
}

Any thoughts on how to improve the code (especially the null-checking, which I cannot tell whether it does any good or if the try-catch ends up doing everything) will be greatly appreciated, with credit provided and the code updated.

Somehow, when I posted this internally, it won “Most Popular Newsfeed of the Month” at our office in January. When I tell you I work for an international development company, that seems to make sense… until I point out that the development the rest of the company does is the other kind of development. That is projects designed to help people in developing countries. So, rather than show how well-received my post was internally, it shows that we’re still early on in our efforts at Social Business.

Categories: Utilities | Tags: , , | 3 Comments

Create a free website or blog at WordPress.com.

%d bloggers like this: