Introducing XALPI – Alternative API for XEO Applications

XALPI

Hi everyone,

I’ve been working on an application, using the XEO Framework, for a while now and there were two situations that I wanted to improve. First it was my inability to write unit tests for my application’s logic (using JUnit, for example) and the other was I had trouble finding which attributes were being used where and overall can’t rely on the compiler to help me out. XEO’s API is very flexible and all but I thought that in order to address these two issues I would have to come up with something on my own.

Notice: This work is not associated with the XEO Framework, although I do work at ITDS (which creates the framework), XALPI does not reflect anything but my own opinion and effort on the subject.

Meet XALPI! (beta)

XALPI stands for XEO ALternative API and is a personal attempt to create a more convenient (for me) API and allow the creation of unit tests. It’s an open source project that you can find on Bitbucket, licensed under the BSD license (rev3), meaning you can do just about anything with it.

You can download it here (see the instructions at the wiki page).

So, what makes XALPI different from XEO’s original API?

  • Provides an interface representing each XEOModel with getters and setters for each attribute (see example bellow)
  • Set iFile values using java.io.File instances
  • Get/Set Lov Values using a class instance (good for searching references) instead of the value itself
  • The description of each attribute/model is placed as javadoc in the generated interfaces / classes
  • Provides an easy API to create lists of objects and iterate a list
  • Provides a new Logger abstraction to allow creating application logic to be tested without needing the XEO Logger (which throws a bunch of errors to the error console when the server is not up and running)
  • Reduces the number of boRuntimeExceptions thrown by the API (only update/destroy throw exceptions)

Each of these situations is (I hope) well explained at the wiki. Although some information may still be missing ( it’s beta after all ) I will, to the best of my abilities, complete it as fast as I can.

An example? Compare the following code (current API) :

public void createHistory(EboContext ctx, BigDecimal patientBoui) throws boRuntimeException {
		Timestamp time = DateUtils.getTodayDateAsTimeStamp();
		long boui = patientBoui.longValue();
        boObjectListBuilder builder = new boObjectListBuilder(ctx, "select FileHistory where user = CTX_PERFORMER_BOUI and file = ? and dateOpen = ?").argsList(boui,time).cache(false);
		boObjectList list = builder.build();
		if (list.getRecordCount() == 0){

			if (logger.isFineEnabled()){
				logger.fine("Created fileHistory for " + patientBoui.longValue());
			}

			boObject historyEntry = boApplication.getDefaultApplication().getObjectManager().createObject(ctx, FileHistory.MODEL_NAME);
			historyEntry.getAttribute(FileHistory.USER).setValueLong(ctx.getBoSession().getPerformerBoui());
			historyEntry.getAttribute(FileHistory.FILE).setValueLong(boui);
			historyEntry.getAttribute(FileHistory.DATE_OPEN).setValueDate(DateUtils.getTodayDate());
			historyEntry.update();
	    } 
	}

With this (XALPI) :

public void createHistory(Patient fileOpened, BaseModel user) throws boRuntimeException{

		Timestamp time = DateUtils.getTodayDateAsTimeStamp();
		FileHistoryList history = Select.FileHistory().where("user = CTX_PERFORMER_BOUI and file = ? and dateOpen = ?").args(fileOpened,time).build();

		if (history.isEmpty()){

			logger.fine("Created fileHitroy for %s",user.getBoui());

			FileHistory history = FileHistoryManager.create();

			history.setDateOpen(DateUtils.getTodayDate());
			history.setFile(fileOpened);
			history.setUser(user);
			history.update();
		}

	}

Check out the rest at the wiki page and tell me if you like it. I’m open to suggestions and improvements

Happy coding!

XEO Community 1.1.0 was released

Hi, today is all about XEO Community, which had a new release (version 1.1.0) back in February. It took a long time (for various reasons) but the commitment is to have more releases this year (the goal it to have one every three months). It took even longer for me to make this blog post, but as you can see no other posts were made in the meantime, for various reasons.

It’s almost time for a new release but, for now, I’m going to talk about what you can find in the current one.

In the time that has passed we’ve added several new features to the code base, such as:

Themes (Skins):
You can now use the boconfig file to set Themes (they will be automatically converted to instances of the Theme XEO Model, which you can also create at runtime), which are basically a set of CSS files to be included in each page. The XEO Framework now comes bundled with a few themes (designed by the ExtJS community mostly, such as the slate theme)

GridExplorer – List with Preview and Searches saves, multiple grouping
The GridPanel component was extended to support three new features:

  • Preview
  • Saved Searches/Views
  • Multi Group

The preview allows you to “preview” (hence the name) an instance being displayed in the list. In the GridExplorer toolbar you can select where to preview the instance (bottom, left or right) and when selecting an instance it will display a preview in that area.

The saved searches/views allows you to customize the view of the GridExplorer (by sorting, grouping, filtering, etc…) and then save those views with a given name, so that those criteria can be easily reapplied later (depending on what you are doing with the information)

Multi-Group support means that you can now group the results in a GridExplorer (well, in reallity, in any GridPanel) by any number of columns. (Previously you could only group by one column)

PostGreSQL support
You can now use the PostGreSQL database in an XEO Application. For every fan of the PostGre database this will be most welcome (support is also included in the XEO Studio plugin)

Region Layouts
One of the things that was really “blocking” the creativity around layouts was the fact that when you created the Main viewer you really only had the choice to design a left-sided tree panel which opens new viewers in a central area. Now you can declare a Main viewer using the regionLayout component (which allows you to created up to four-regions – north, west, east, south with the fifth region being the center tabpanel). In each of those regions you can regular components to define your interface.

ToolBar with Input Components and Profile restriction
It’s sometimes useful to have not only buttons in a toolbar but also input elements. From this version on, you can use text, numeric, date e combox components in a toolbar. Toolbars can also restrict their menus to only users who have a given profile (much like the case with the TreePanel component)

TreePanel Toolbar
TreePanels can have a child TreePanelToolbar component which allows you to customize a main viewer TreePanel with a set of buttons that you deem appropriate. Any TreePanel can use the TreePanel toolbar, it’s used just like the regular toolbar component.

Lookups with Favorites Selections
Lookup Components can now toggle a “favorites” feature, which means that for each user in each relation, the component can remember the selections made by that user and present them in a quick way to user.

Multi-page selections (and selection counter)
Selection of instances in a Lookup viewer can be preserved across page navigation. Up until now you had to select instances from one page, confirm the selection and then do it again in instances of another page. Also, when multiple selections are possible, a small counter with total instances selected appears in the panel’s toolbar.

Lovs from Database Tables
Lists of values are typically static. but from now on you can declare a Lov as having its values retrieved from a SQL query. To do that you create an empty Lov and then use the Administration interface to define the SQL query to execute.

CardIdLinks in Columns
In any type of GridPanel you can now set the columns that represent relations with instances display the label with a link to open the edit viewer for that instance (you’ll need to declared the column as a xeo:columnAttribute and use the enableCardIdLink property.

Inline Bridge with Favorite Selections
Collection attributes are displayed using the Bridge component, now you can display them inline as a “regular” attribute (such as the Lookup component). You can also activate the favorite selections for this type of component

Quick Date Input (DateField)
Date Fields can now have an abbreviated method of input by using the ‘.’ to select the current date, and the ‘.+3’ / ‘.-5’ syntax to select three days from now and five days ago (respectively)

Cardinality restriction in collections
XEO Models have a minOccurs and maxOccurs property in collection attributes which was not being used. Now when you set a minOccurs bigger than 0 or a maxOccurs smaller than ‘N’ the platform will enforce that situation (selecting instances in a lookup will even prevent you from selection if you have already reached the limit for that collection)

Charts with SQL Bind parameters and Label Formatting
Charts can now have bind parameters when using a SQL query and you can provide a map between labels coming from the data source and what to display in chart.

Column wrap (LongText)
GridPanels having columns with LongText content can now be wrapped so that the entire content is displayed in the visible space (property wrapText)

boObjectListBuilder (Builder Pattern to create boObjectLists)
If you ever thought that creating boObjectList instances required you to know a lot of parameters (when you need to tweak things a bit) you can now use the boObjectListBuilder class which implements the builder pattern to create boObjectList instances like the following:

Favorites (Edit viewers)
Edit viewers can now be added to the list of favorites for a given user. This allows users that do much work in a given instance to mark it, and then quickly have access to it using the favorites list.

Lots of Bug fixes: I won’t even start enumerating them as there were lots of them. We really need another way of managing this.

I’ll make a few posts explaining some of the new features in the following days

CreateView vs CreateChildView why do I lose my boObject reference?

When you are developing an application using XEO you’ll need to open specific views as a result of certain actions. In order for you to achieve that you need to create the view in memory and for that you have two choices:

XUIViewRoot viewRoot = getSessionContext().createChildView("viewers/path/to/viewer/Viewer.xvw");

or

XUIViewRoot viewRoot = getSessionContext().createView("viewers/path/to/viewer/Viewer.xvw");

The main difference between the two is regarding the current context. Creating a view with createView uses a new context and switches the context immediately upon invocation (meaning you loose access to anything that was available in the current context) . If you use the createChildView method you maintain the same context in the two views ( which is important if the two views share some relationship – hence the name create ” child ” view)

So if your two views have no relationship but you need information for the current context… Save them in variables before creating the view – or else. Most of the times createChildView is the correct usage, but if the two views are disconnected, use createView.

Happy coding!