Chapter 2: My first OX project
Create a new project
First open your Eclipse and make its workspace the one that comes with the OpenXava distribution.
Using the appropriate Eclipse Wizard create a new Java Project named
Management. Now you have a new empty Java project in the workspace, the next step is to give it the correct shape for an OpenXava project.
Go to the project
OpenXavaTemplate and edit the file
CreateNewProject.xml in this way:
<property name="project" value="Management" />
Now execute
CreateNewProject.xml using Ant. You can do it with
Right Button on CreateNewProject.xml > Run as > Ant Build
Select the project
Management and press F5 for refreshing.
And now you have a new project ready to start working, but before continuing you need to configure the database.
Configure database
OpenXava generates a JavaEE/J2EE application intended to be deployed in a Java Application Server (since v2.0 OpenXava applications also run in a simple servlet container, as Tomcat). In OpenXava you only need to indicate the Data Source JNDI and then configure the data source in your application server. Configuring a data source in an application server is out of the scope of this guide, nevertheless you have below detailed instructions to configure a database in order to run this first project using the Tomcat included in OpenXava distribution as application server and Hypersonic as database. This Tomcat is in the folder
openxava-3.x/tomcat.
With Tomcat stopped edit the file
context.xml in Tomcat's directory
conf. In this file add the next entry:
<Resource name="jdbc/ManagementDS" auth="Container" type="javax.sql.DataSource"
maxActive="20" maxIdle="5" maxWait="10000"
username="sa" password="" driverClassName="org.hsqldb.jdbcDriver"
url="jdbc:hsqldb:hsql://localhost:1666"/>
The main thing here is the JNDI name, this is the only thing referenced from OpenXava, in this case
ManagementDS. The
driverClassName and
url attributes depend on your particular database, in this case Hypersonic is used.
Your first business component
Creating an OpenXava business component is easy: The definition of each component is a Java class with annotations. In order to begin you have to create a class called
Warehouse:
- Put on src folder and use the Right Button > New > Package
- Create a package named org.openxava.management.model
- Put on package org.openxava.management.model and use Right Button > New > Class
- Create a class named Warehouse
Now edit your new class and write this code:
package org.openxava.management.model;
import javax.persistence.*;
import org.openxava.annotations.*;
@Entity
public class Warehouse {
@Id @Column(length=3) @Required
private int number;
@Column(length=40) @Required
private String name;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
This class contains (and it will be contain) all data needed by the application about the Warehouse business concept. At the moment we only have data structure, but in this class you can put the mapping against the database, the business logic, the visual presentation, the tabular data management, etc.
Really this class is an
Entity that follows the EJB3 standard. For defining a class as a entity you only need to use the
@Entity annotation in the class declaration.
In entity you define properties, let's see how:
@Id // 1
@Column(length=3) // 2
@Required // 3
private int number; // 4
private int getNumber() { // 4
return number;
}
private void setNumber(int number) { // 4
this.number = number;
}
This is its meaning:
- @Id: Indicates if this property is part of the key. The key is a unique identifier of the object and usually matches with the primary key of a database table.
- @Column(length= ): Length of data. It's optional, but useful to display better user interfaces and generating database tables.
- @Required: Indicates if it's required to validate the existence of data for this property just before creation or modification.
- The property defined in the usual way for a Java class. All valid types for a Java property are applicable here, including integrated types, JDK classes and custom classes.
The possibilities of the property definition go far from what is shown here, you can see a more complete explanation in
Model chapter.
The table
Before testing the application you have to create the table in database. Follow these steps:
- Start your database server: From command line go to openxava-3.x/tomcat/bin folder and execute:
- In Linux/Unix: ./start-hsqldb.sh management-db 1666
- In Windows: start-hsqldb management-db 1666
- Create the table:
- Edit Management/build.xml. Search the ant target updateSchema.
- Put a correct value for schema.path, in this case “../OpenXavaTest/lib/hsqldb.jar”.
- Execute the ant target updateSchema.
- Start Tomcat and now everything is ready.
Executing your application
After your hard work it is time to see the fruit of your sweat. Let's go.
And now you can play with your module and see its behavior.
Also you can deploy your module as a JSR-168 portlet, in this way:
- Execute ant target generatePortlets.
- Take the file Management.war in the folder openxava-3.x/workspace.dist/Management.dist and deploy it into your Portal Server.
Automating the tests
Although it seems that the most natural way to test an application is to open a browser and use it like a final user; in fact it is more productive automating the tests, in this way as your system grows, you have it tied and you avoid to break it when you advance.
OpenXava uses a test system based on JUnit and HttpUnit. The OpenXava JUnit tests simulate the behavior of a real user with a browser. This way you can replicate exactly the same tests that you can do directly with an internet browser. The advantage of this approach is that you can test easily all layers of your program from user interface to database.
If you test the module manually you usually create a new record, search it, modify and finally delete it. Let's do this automatically:
First you must create a package for the test classes,
org.openxava.management.tests, and then add the
WarehouseTest class to it, with next code:
package org.openxava.management.tests;
import org.openxava.tests.*;
/**
* @author Javier Paniza
*/
public class WarehouseTest extends ModuleTestBase {
public WarehouseTest(String testName) {
super(testName, "Management", "Warehouse"); // 1
}
public void testCreateReadUpdateDelete() throws Exception {
// Create
execute("CRUD.new"); // 2
setValue("number", "7"); // 3
setValue("name", "JUNIT Warehouse");
execute("CRUD.save");
assertNoErrors(); // 4
assertValue("number", ""); // 5
assertValue("name", "");
// Read
setValue("number", "7");
execute("CRUD.search");
assertValue("number", "7");
assertValue("name", "JUNIT Warehouse");
// Update
setValue("name", "JUNIT Warehouse MODIFIED");
execute("CRUD.save");
assertNoErrors();
assertValue("number", "");
assertValue("name", "");
// Verify if modified
setValue("number", "7");
execute("CRUD.search");
assertValue("number", "7");
assertValue("name", "JUNIT Warehouse MODIFIED");
// Delete
execute("CRUD.delete");
assertMessage("Warehouse deleted successfully"); // 6
}
}
You can learn from this example:
- Constructor: In the constructor you indicate the application and module name.
- execute: Allows to simulate a button or link click. As an argument you send the action name; you can view the action names in OpenXava/xava/default-controllers.xml (the predefined controllers) and Management/xava/controllers.xml (the customized ones). Also if you move the mouse over the link your browser will show you the JavaScript code with the OpenXava action to execute. That is execute(“CRUD.new”) is like click in 'new' button in the user interface.
- setValue: Assigns a value to a form control. That is, setValue(“name”, “Pepe”) has the same effect than typing in the field 'name' the text “Pepe”. The values are always alphanumeric because they are assigned to a HTML form.
- assertNoErrors: Verify that there are no errors. In the user interface errors are red messages showed to user and added by the application logic.
- assertValue: Verify if the value in the form field is the expected one.
- assertMessage: Verify if the application has shown the indicated informative message.
You can see that is very easy to test that a module works; writing this code can take 5 minutes, but at end you will save hours of work, because from now on you can test your module just in 1 second, and because when you break the Warehouse module (maybe touch in another part of your application) your test warns you just in time.
For more details have a look at the JavaDoc API of
org.openxava.tests.ModuleTestBase and examine the examples in
org.openxava.test.tests of OpenXavaTest.
By default the test runs against the module in alone (non portal) mode (that is deployed with
deployWar). But if you want it's possible to test against the portlet version (that is deployed with
generatePortlets). You only need to edit the file
properties/xava-junit.properties and write:
liferay.url=web/guest
This is for testing against Liferay. Also it's possible to test against a JetSpeed2 portal, look at
OpenXavaTest/properties/xava-junit.properties to learn more.
The labels
Now everything works well, but a little detail remains yet. Maybe you want to define the labels to be show to the user. The way is to write a file with all labels, thus you can translate your product to another language with no problems.
To define the labels you only have to edit the file
Management-labels_en.properties in
i18n folder. Edit that file and add:
Warehouse=Warehouse
You do not have to put all properties, because the more common cases (number, name, description and a big etc) is already included with OpenXava in English, Spanish, Polish, French, German, Indonesian and Catalan.
If you wish the version in an other language (Spanish for example), you only need to copy and paste with the appropriate suffix. For example, you can have a
Management-labels_es.properties with the next content:
Warehouse=Almacén
The OpenXava default labels and messages are in
OpenXava/i18n/Labels.properties and
OpenXava/i18n/Messages.properties. If you want to override some of these resources you do not need to edit these files, instead, you can use the same key names in the resource files of your project, then your labels and messages will be used instead of the standard ones of OpenXava
(new in v2.0.3). For example, if you want to change the standard message in list mode '
'There are 23663 objects in list” for other, you have to add to your
Management-messages_en.properties this entry:
# list_count is in Messages_en.properties of OpenXava, this is an example
# of overriding a standard openxava message
list_count=There are {0} records in list
Now, your application will show “There are 23663 records in list” instead of the default OpenXava message
“'There are 23663 objects in list”.
If you want to know more about how to define labels of your OpenXava elements please look in
OpenXavaTest/i18n.