lunes, 3 de octubre de 2011

Module Packager

Module Packager is the name of a new extension module available for Openbravo 3 and 2.50 versions. It is released under the Openbravo Public License and it can be installed through the Module Management window of your Openbravo instance.

This module is mainly intended for developers who want to reduce the time it costs to package a module, and for the users who are not comfortable running commands into the shell terminal.

When installing this module, it adds a button inside the Module window that allows the developer to run all the common tasks that are needed for packaging a module in just one click. The button is available for modules set as in development.

The Module Packager currently supports:
- Exporting the datasets configured for the module (if any).
- Exporting the database.
- Exporting the translation XML files, saving them into the appropriate folder (only in case of translation modules). To perform this task it delegates to the Translations Management Extension developed by Marcos Bernal.
- Packaging the module into an obx file ready to be published into the Central Repository

The developer can manually selects the tasks he wants to be run each time, thus simplifying and speeding up the process of packaging a module.

martes, 1 de marzo de 2011

Using messages with parameters in Java

Messages are one of the most important parts of a software. They enable the application to inform the user about errors, warnings or other important information. That's why we should give them special consideration.

Users: Sometimes developers find it difficult to write a simple and clear message. We are used to writing sentences in a cryptic computer language, so it's natural for us to also write cryptic messages (that are almost impossible for an average user to understand).

Developers: We must appreciate that a user expects messages in his natural language, not in machine language... Yes, I know it sounds strange and difficult but we need to make an effort... It is also important to consider translators; the simpler and clearer the message, the more likely it is to be correctly translated.

there is a process which executes some kind of business logic. Imagine the process fails in the middle of the execution with the following error:
...and now try to imagine the average-user's face!
Yeah, I know all the developers are saying: "no problem, we can dive into the application logs, we can debug the code, etc."; but the user isn't able to do that. This message is a "show stopper" for them... and we don't want this situation to happen.

As I said before, a message must be written in a "natural" language and must try to be as helpful as possible, specially when dealing with errors. In the previous example, a good message could be:
The invoice IV-1000004 has not been posted yet. Remember that invoices must be posted before running this process

For developing that we could think about creating two different messages, one for "The ", and the other one for " has not been posted yet. Remember that invoices must be posted before running this process". After that, in the Java code, we could easily concatenate the invoice number between these two messages... Wrong!!
Again, the developer must consider the localizer who is faced with translating two meaningless strings of text.

Translating is a very difficult (and time consuming) task. A localizer must be provided with meaningful phrases (where the context is clear) for translating, otherwise the translation will almost certainly be inaccurate.

So, the best way to keep both our users and localizers happy would be to create the message with the invoice number as a parameter.

In Java we have all the flexibility to implement our own parametrized messages framework. In my developments I use the String.format(java.lang.String, java.lang.Object...) method, which is very similar to the C's printf().
Let's see how it works:

* The error message included into the Application Dictionary is: "The invoice %s has not been posted yet. Remember that invoices must be posted before running this process". Observe the %s, that represents our parameter.

* The Java code for passing the invoice document number to the message is as easy as:
String message = String.format(Utility.messageBD(new DalConnectionProvider(),
"BLOG_INVOICE_NOTPOSTED", getLang()), invoiceDocNo);

As usual, we recover the "BLOG_INVOICE_NOTPOSTED" message from the Application Dictionary using the Utility.messageBD() method.
Then, the recovered message is used as the first parameter of the String.format() static method. The second parameter is the invoiceDocNo string (IV-1000004 in the example), that will replace the %s of our message.

With this very basic considerations, users and localizers will be very happy and the product will be even better.