Migration

How to update your project to the latest OpenXava?

  • Download the latest OpenXava distribution and uncompress it in a new location.
  • If you current OpenXava version is older than 5.0 add a new empty Java project from Eclipse in your workspace called Addons.
  • Stop your Eclipse.
  • Remove the Addons (since v5.0) and OpenXava projects from your workspace.
  • Copy the Addons and OpenXava projects from the workspace of the new OpenXava to yours.
  • Start your Eclipse.
  • Build All (Ctrl-B).
  • Execute the updateOX ant target of your project.
  • Refresh (with F5) your project.
  • Revise the instructions below.
  • If your application fails:
    • Stop tomcat and remove the temp and work folders of Tomcat (inside the Eclipse use Clean Tomcat Work Directory... on your server in Server view).
    • Remove your application from Tomcat and add it again.

Migration from OpenXava 5.7.1 to OpenXava 5.8

New actions in list mode (for JUnit tests)

The list mode has new actions available for the users (List.changeColumnName and ImportData.importData), therefore if you test for all present actions in your junit tests, you need to modify it in order to take into account the new List.changeColumnName and ImportData.importData actions:
private String [] listActions = {
    "Print.generatePdf",
    "Print.generateExcel",
    "ExtendedPrint.myReports",
    "CRUD.new",
    "CRUD.deleteSelected",
    "CRUD.deleteRow",
    "Mode.detailAndFirst",
    "Mode.split",
    "List.filter",
    "List.orderBy",
    "List.viewDetail",
    "List.hideRows",
    "List.sumColumn",
    "List.changeConfiguration",
    "ListFormat.select",
    "List.changeColumnName", // ADD THIS ENTRY
    "ImportData.importData"  // ADD THIS ENTRY
};
assertActions(listActions);

Delete action is not available while creating a new element (for JUnit tests)

In v5.8 when the user clicks on New the Delete action is hidden. This does not affect your application code but if you use assertActions() in your tests maybe you have to adapt them:
String [] actionsAfterNew = {
 "Navigation.previous",
 "Navigation.first",
 "Navigation.next",
 "CRUD.new",
 "CRUD.save",
 // "CRUD.delete", // REMOVE THIS LINE
 "CRUD.refresh",
 "Mode.list",
 "Mode.split",
 "List.filter",
 "List.orderBy",
 "Print.generatePdf",
 "Print.generateExcel"
};
assertActions(actionsAfterNew);

Search action no longer available in detail mode (for JUnit tests)

If you use assertActions() in your tests you should adapt them:
String [] actions = {
 "Navigation.previous",
 "Navigation.first",
 "Navigation.next",
 "CRUD.new",
 "CRUD.save",
 "CRUD.delete",
 // "CRUD.search", // REMOVE THIS LINE
 "CRUD.refresh",
 "Mode.list",
 "Mode.split",
};
assertActions(actions);
If you use CRUD.search in your test you can change it by CRUD.refresh, that is change:
execute("CRUD.search");
setValue("number", "123");
execute("Search.search");
By:
setValue("number", "123");
execute("Search.search");
Moreover, if you want that the search action comes back use the new SearchForCRUD controller that just contains the classic seach action. To define a module with search in application.xml add the SearchForCRUD controller:
<module name="Delivery">
    <model name="Delivery"/>
    <controller name="Typical"/>
    <controller name="SearchForCRUD"/> <!-- ADD THIS LINE -->
</module>
Another option si to define it in controllers.xml in this way:
<controller name="Author">
    <extends controller="Typical"/>
    <extends controller="SearchForCRUD"/> <!-- ADD THIS LINE -->
    <action name="doSomething"
        class="com.mycompany.test.actions.DoSomethingAction" />
</controller>
Even if you add the search action back with SearchForCRUD you have to change your JUnit tests because search is no longer in CRUD but in SearchForCRUD. Therefore you have to change:
execute("CRUD.search");
By:
execute("SearchForCRUD.search");
Also we have a TypicalWithSearch controller that have all the Typical action plus search, just as the old Typical. If you want to use it by default write the next code at the beginning of your application.xml:
<default-module>
    <controller name="TypicalWithSearch"/>
</default-module>

Modules with no rows starts executing new action (for JUnit tests)

You should touch JUnit tests with modules without rows, because they now starts in detail mode. For example, you should change a code like this:
public void testCreateExamWithAtLeastOneQuestion() throws Exception {
  assertListRowCount(0); // NOW THIS LINE FAILS
  execute("CRUD.new");
  setValue("name", "ADMISSION");
  execute("CRUD.save");
  ...
}
If the module has no rows, now it starts in detail mode so the first line will fail. We can just change to list mode at the beginning:
public void testCreateExamWithAtLeastOneQuestion() throws Exception {
  execute("Mode.list"); // ADD THIS LINE
  assertListRowCount(0);
  execute("CRUD.new");
  setValue("name", "ADMISSION");
  execute("CRUD.save");
  ...
}
Or if you test goes directly to detail mode, like in this example, just remove the first part of the test:
public void testCreateExamWithAtLeastOneQuestion() throws Exception {
  // assertListRowCount(0); // REMOVE THIS LINE
  // execute("CRUD.new"); // REMOVE THIS LINE
  setValue("name", "ADMISSION");
  execute("CRUD.save");
  ...
}

Migration from OpenXava 5.7 to OpenXava 5.7.1

No issues.

Migration from OpenXava 5.6.1 to OpenXava 5.7

Action List.changeConfigurationName renamed as List.changeConfiguration (for JUnit tests)

The list action List.changeConfigurationName now is List.changeConfiguration, therefore if you test for all present actions in your junit tests, you need to modify the name of this action:
private String [] listActions = {
  "Mode.detailAndFirst",
  "Mode.split",
  "List.filter",
  "List.orderBy",
  "List.viewDetail",
  "List.hideRows",
  "List.sumColumn",
  // "List.changeConfigurationName" // REMOVE THIS ENTRY
  "List.changeConfiguration" // ADD THIS ENTRY
};
assertActions(listActions);

Improved default properties for list and collections (for JUnit tests)

Until now when @Tab for list, or @ListProperties for collections, is omitted by default OpenXava shows all the plain properties of the entity. Since v5.7 when @Tab/@ListProperties is not present the properties to show are the plain ones, the ids of the references, the name, description or title of the references or if not present the first not id property of the reference. Moreover, the plain properties that are just oids are excluded.
For example, if we have this class without @Tab:
@Entity
public class Invoice {
 private int year;
 private int number;
 private Date date;
 @ManyToOne
 private Customer customer;
 
 @Stereotype("FILES") @Column(length=32)
 private String files;
 
 ...
}
In previous versions we get in list: year, number, date, files
In v5.7 we get: year, number, date, customer.number, customer.name
If you have JUnit tests againts entities without @Tab maybe you'll have to adapt them.

@NewAction no longer define the add action in regular @OneToMany collections

Since v5.7 @OneToMany collections without cascade REMOVE have available at the same time a 'New' action to create new elements and a 'Add' action to add elements from existing ones. Before v5.7 only the 'Add' action was available and it could be defined using @NewAction. Now we have a new annotation, @AddAction, for 'Add' action and we use the old @NewAction only for 'New' action.
You should change @NewAction by @AddAction in collections without cascade REMOVE. Change:
@NewAction("Invoice.addDeliveries")
@OneToMany(mappedBy="invoice")
private Collection<Delivery> deliveries;
By:
@AddAction("Invoice.addDeliveries")
@OneToMany(mappedBy="invoice")
private Collection<Delivery> deliveries;

Collections of entities with no REMOVE cascade allow to edit the elements (for JUnit tests)

You don't need to change your application code, just adapt your JUnit tests changing:
execute("Collection.view", "row=1,viewObject=xava_view_customers");
By:
execute("Collection.edit", "row=1,viewObject=xava_view_customers");
Note, now it's not "Collection.view" but "Collection.edit".

Automatic label for references in list optimized (for JUnit tests)

When in a list we have a property from a reference and the property name is "name", "description" or "title", the property name is omitted, OpenXava shows just the reference name. That is, instead of "Name of Customer" now is just "Customer". This does not affect your application code at all, but if you test list labels in your JUnit tests you should adapt them.
Change this:
assertLabelInList(4, "Name of Customer");
By this:
assertLabelInList(4, "Customer");

Migration from OpenXava 5.6 to OpenXava 5.6.1

No issues.

Migration from OpenXava 5.5.1 to OpenXava 5.6

The action ExtendedPrint.myReports is no longer available by default (for JUnit tests)

Therefore if you test for all present actions in your JUnit tests, you need to modify it removing ExtendedPrint.myReports from the list:
private String [] listActions = {
    "Print.generatePdf",
    "Print.generateExcel",
    // REMOVE THIS LINE "ExtendedPrint.myReports",
    "CRUD.new",
    "CRUD.deleteSelected",
    ...
};
assertActions(listActions);
Though the action is not available by default, it still exists in OpenXava and works perfectly. Indeed there is a new controller TypicalExtendedPrint to facilitate its use. If you want to continue using the My reports feature just change Typical by TypicalExtendedPrint in your application.xml and controllers.xml, even you can declare it as default controller.

New action in list (for junit tests)

The list has a new action available for the users (List.changeConfigurationName), therefore if you test for all present actions in your junit tests, you need to modify it in order to take into account the new List.changeConfigurationName action:
private String [] listActions = {
  "Mode.detailAndFirst",
  "Mode.split",
  "List.filter",
  "List.orderBy",
  "List.viewDetail",
  "List.hideRows",
  "List.sumColumn",
  "List.changeConfigurationName" // ADD THIS ENTRY
};
assertActions(listActions);

Migration from OpenXava 5.5 to OpenXava 5.5.1

Needed to call super inside setUp() of tests before using JPA

Since v5.5.1 the JPA initialization ModuleTestBase tests is done in the setUp() method, so if you use JPA inside a setUp() method you have to call super before. That is, if you have a code like this in your test:
protected void setUp() throws Exception {
    createEntitiesUsingJPA(); // Now it fails, because JPA is not still initialized
    super.setUp();
}
Change it by:
protected void setUp() throws Exception {
    super.setUp(); // JPA is initialized here
    createEntitiesUsingJPA();
}

Migration from OpenXava 5.4.1 to OpenXava 5.5

@DescriptionsList combos are not longer HTML select (only if you use HtmlUnit API)

Combos for @DescriptionsList are now created with a HTML input text plus some JavaScript code and CSS to emulate a combo. This does not require any change in your application code, it even does not require that you change your jUnit tests if you just use the ModuleTestBase provided methods. However, if you use the HtmlUnit API directly, for example by means of getHtmlPage() or getWebClient() in your tests, and you manage a @DescriptionList combo. Then you have to adjust your code, changing:
form.getSelectByName("ox_MyApp_MyModule__myReference___id").setSelectedAttribute("TheValue", true);
By:
HtmlInput comboInput = form.getInputByName("ox_MyApp_MyModule__myReference___id");
comboInput.setValueAttribute("TheValue");
((HtmlInput) comboInput.getPreviousElementSibling()).setValueAttribute("Something"); // A trick to avoid that JavaScript reset the real value
((HtmlInput) comboInput.getNextElementSibling()).setValueAttribute("Something"); // A trick to avoid that JavaScript reset the real value

Migration from OpenXava 5.4 to OpenXava 5.4.1

No issues.

Migration from OpenXava 5.3.2 to OpenXava 5.4

Icons instead of images for actions

Since v5.4 the standard actions of OpenXava use icons from Material Design Icons instead of gif or png images. The image attribute of <action/> in controllers.xml continue to work as always, however we have a new attribute icon that is the one used in the standard actions. The effect is that in your application all the standard actions will use the new monochrome icons and your own actions will use the old colorful gif and png images. This mix could be a little ugly, to fix it just change image by icon in your actions. For example, change:
<action name="delete" mode="detail" confirm="true"
    class="com.mycompany.myapp.actions.MyDeleteAction"
    image="delete.gif"
    keystroke="Control D"/>
By this:
<action name="delete" mode="detail" confirm="true"
    class="com.mycompany.myapp.actions.MyDeleteAction"
    icon="delete"
    keystroke="Control D"/>
To see all available icons look at Material Design Icons.
On the other hand, if your prefer to continue with the old fashion color icons, just add the next line in xava.properties:
useIconsInsteadOfImages=false
Then all the actions, included the standard ones, will use the old colorful images.

Migration from OpenXava 5.3.1 to OpenXava 5.3.2

No issues.

Migration from OpenXava 5.3 to OpenXava 5.3.1

HSQLDB jar moved from OpenXavaTest to OpenXava

If you reference this jar you have to change the path. For example, if you uses HSQLDB in some of your projects, you should change in updateSchema target of your build.xml this:
<property name="schema.path" value="../OpenXavaTest/lib/hsqldb.jar"/>
By this:
<property name="schema.path" value="../OpenXava/lib/hsqldb.jar"/>

Migration from OpenXava 5.2.1 to OpenXava 5.3

Hibernate upgraded to 4.3

If you use JPA API or basic use of Hibernate API you have to do nothing. However, if you use advanced Hibernate features maybe this upgrade affects you.
For example, if you have your own Hibernate types (UserType), you have to change in your type definition this:
public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
By:
public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor sessionImplementor, Object owner) throws HibernateException, SQLException {
And this:
public void nullSafeSet(PreparedStatement ps, Object value, int index) throws HibernateException, SQLException {
By:
public void nullSafeSet(PreparedStatement ps, Object value, int index, SessionImplementor sessionImplementor) throws HibernateException, SQLException {
Of course, if you call these methods you have to adapt the calling code too. For example, a code like this:
((UserType) hibernateType).nullSafeSet(ps, o, 1);
Now it would be:
((UserType) hibernateType).nullSafeSet(ps, o, 1, null);
Note that sending a null for the new extra parameter is enough.
Moreover, instead of Hibernate.INTEGER you have to use IntegerType.INSTANCE.
The way of registering events has changed, it affects you only if you use XML components with the JPA API. In this case you have to remove the event registration from the persistence.xml, as following:
<persistence-unit name="default" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
 
    <properties>
        <property name="hibernate.ejb.cfgfile" value="/hibernate-jpa.cfg.xml"/>
        <!-- REMOVE THE NEXT LINES
        <property name="hibernate.ejb.event.pre-insert" value="org.openxava.hibernate.impl.CalculatorsListener, org.openxava.hibernate.impl.ReferenceConverterToDBListener, org.openxava.hibernate.impl.DefaultValueCalculatorsListener"/>
        <property name="hibernate.ejb.event.pre-update" value="org.openxava.hibernate.impl.CalculatorsListener, org.openxava.hibernate.impl.ReferenceConverterToDBListener"/>
        <property name="hibernate.ejb.event.pre-delete" value="org.openxava.hibernate.impl.CalculatorsListener"/>
        <property name="hibernate.ejb.event.post-load" value="org.openxava.hibernate.impl.CalculatorsListener"/>
        -->
    </properties>
</persistence-unit>
Also if you use XML components you no longer can have a reference used as key if the value does not exist in the referenced table. This case is no longer allowed by Hibernate. This case has never been supported in JPA. You should think in a different way of solving your issue, such as adding an autogenerated key or creating the corresponding row in the referenced table.
With Hibernate 4.3 the default way of releasing connections has changed, so you could find a "Could not open connection error". To avoid it add the next entry to your persistence.xml:
<persistence-unit name="default">
    ...
    <properties>
        ...
        <!-- Add the next entry -->
        <property name="hibernate.connection.release_mode" value="after_transaction"/>
 
    </properties>
 
</persistence-unit>

Hibernate Validator 3 dropped

Until now we have included both, the old Hibernate Validator 3 and the latest Hibernate Validator version in OpenXava distribution for maximum backward compatibility. Unfortunately Hibernate 4.3 does not support Hibernate Validator 3, so we have to remove it from OpenXava.
If you just use validation annotations as @Max, @Length, @Size, etc. it's enough to change the imports, change:
import org.hibernate.validator.*;
By:
import javax.validation.constraints.*;
import org.hibernate.validator.constraints.*;
In the case of @Digits apart of changing the above imports you have to change the parameter names, changing this:
@Digits(integerDigits=10, fractionalDigits=6)
By:
@Digits(integer=10, fraction=6)
You cannot longer use InvalidStateException of Hibernate Validator 3. Therefore, if you use it to throw a validation error from your entity or action you have to change it by other exception. For example, a code like this:
@PreRemove
public void validateOnRemove() {
    if (number == 1) {
        throw new InvalidStateException(
            new InvalidValue [] {
                new InvalidValue(
                    "one_not_deletable", getClass(), "number",
                    getNumber(), this)
            }
        );
    }
}
Now it could be written in this way:
@PreRemove
public void validateOnRemove() {
    if (number == 1) {
        throw new javax.validation.ValidationException("one_not_deletable");
    }
}
If you have defined your own validator with the Old Hibernate Validator you should rewrite it using the Bean Validation standard. Don't worry, converting it is very easy. In your annotation change @ValidatorClass by @Constraint and add groups() and payload(), thus:
@Constraint(validatedBy = MyValidator.class) // Instead of @ValidatorClass(PropertyValidatorValidator.class)
public @interface MyAnnotation {
 
    ...
 
    // Add the next code
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
 
}
And in the validator class change this:
public class RequiredValidator implements Validator<Required> {
By:
public class RequiredValidator implements ConstraintValidator<Required, Object> {
And this:
public boolean isValid(Object value) {
By:
public boolean isValid(Object value, ConstraintValidatorContext context) {
You can keep the rest of your code as is.

@Required, @PropertyValidator and @EntityValidator are Bean Validation restriction

Before, they were Hibernate Validator 3 restrictions. If you do your own commit and try to catch the validation exception you have to change the exception to catch. If you have a code like this:
try {
    XPersistence.commit();
}
catch (RollbackException ex) {
    if (ex.getCause() instanceof InvalidStateException) {
        InvalidStateException iex = (InvalidStateException) ex.getCause();
        int invalidValuesCount = iex.getInvalidValues().length;
        String property = iex.getInvalidValues()[0].getPropertyName();
        String message = iex.getInvalidValues()[0].getMessage();
        ...
    }
}
You should write it in this way:
try {
    XPersistence.commit();
}
catch (RollbackException ex) {
    if (ex.getCause() instanceof ConstraintViolationException) {
        ConstraintViolationException cex = (ConstraintViolationException) ex.getCause();
        int invalidValuesCount = cex.getConstraintViolations().size();
        ConstraintViolation v = cex.getConstraintViolations().iterator().next();
        String property = v.getPropertyPath().toString());
        String message = v.getMessage());
        ...
    }
}

Prefix for JNDI in older Tomcats

Hibernate 4.3 uses a different way for looking the JNDI resources that works fine with Tomcat 7.0.27 (and better) and Tomcat 6.0.36 (and better) but fails with previous versions. This is not a bug of Hibernate but a Tomcat bug. Fortunately, there is a trick to make the new Hibernate works even with older Tomcat versions, just add a // to the JNDI name. That is, if you're using a Tomcat version previous to 7.0.27 or 6.0.36 just change in your persistence.xml this:
<non-jta-data-source>java:comp/env/jdbc/YourApplicationDS</non-jta-data-source>
By this:
<non-jta-data-source>java://comp/env/jdbc/YourApplicationDS</non-jta-data-source>
And in hibernate.cfg.xml change this:
<property name="hibernate.connection.datasource">java:comp/env/jdbc/YourApplicationDS</property>
By this:
<property name="hibernate.connection.datasource">java://comp/env/jdbc/YourApplicationDS</property>
Note the // before comp. If you use JNDI names in other places you shoud change them too. The good thing is that newer Tomcat versions also work in this way, so if you use always this notation your application will work in any Tomcat.

EL libraries upgrade for Tomcat 6

If you're using Tomcat 6 copy el-api.jar and jasper-el.jar from the Tomcat lib folder included in OpenXava (or any Tomcat 7) to the lib folder of your Tomcat 6. This is required by the latest Hibernate Validator version.

Automated Business Logic (ABL) library dropped

Unfortunately, ABL does not support Hibernate 4.3. Moreover, ABL has been discontinued since 2012, so it will not support Hibernate 4.3 in the future. Therefore, we have not other option but removing ABL from OpenXava distribution. Fortunately, moving the logic in ABL annotations to Java code is easy. For example, if you have an ABL logic class like this:
public class OrderLogic {
 
    @Formula("productPrice * qtyOrdered")
    public void deriveAmount() { }
 
}
Remove the above class and move the calculation in @Formula annotation to a @PrePersist and @PreUpdate method in the entity, thus:
@Entity
public class Order {
 
    ...
 
    @PrePersist @PreUpdate
    private void deriveAmount() {
        amount = new BigDecimal(qtyOrdered).multiply(productPrice);
    }
}
Furthermore, you have to remove the next entry from your persistence.xml:
<property name="hibernate.current_session_context_class"
    value="com.autobizlogic.abl.session.LogicThreadLocalSessionContext"/>

schema.path required in generateSchema ant target

This affects to generateSchema not to updateSchema. If you have a generateSchema target in your build.xml, add schema.path, as following:
<!-- Generates the schema from scratch. Shows it in console, but does not execute it -->
<target name="generateSchema">
 
    <ant antfile="../OpenXava/build.xml" target="generateSchemaJPA">
        <property name="persistence.unit" value="junit"/>
        <!-- ADD THE NEXT LINE FOR V5.3 -->
        <property name="schema.path" value="../OpenXavaTest/lib/hsqldb.jar"/>
    </ant>
 
</target>

Migration from OpenXava 5.2 to OpenXava 5.2.1

Entity from View has nulls for non-existing references

Until v5.2 all references of the entity obtained via getView().getEntity() have value, even if the references do not exist. It was producing a very odd bug because JPA tries to save transient objects as references. Since v5.2.1, empty references are null, this is more natural (it works in the same way when you get the object from database) and it solves the above bug.
If you have code that relies in this behavior you must change it. That is, you have to make changes like the next one:
Invoice invoice = (Invoice) getView().getEntity();
if (invoice.getCustomer().getNumber() == 0) { // In v5.2 if customer is empty an empty customer is returned
By:
Invoice invoice = (Invoice) getView().getEntity();
if (invoice.getCustomer() == null) { // In v5.2.1 if customer is empty a null is returned

Migration from OpenXava 5.1.x to OpenXava 5.2

HtmlUnit upgraded to 2.15

If you use HtmlUnit directly from your jUnit test by means of getHtmlPage() or getWebClient() you should adapt your code to the new HtmlUnit 2.15 API. For example, you should change:
getWebClient().setCssEnabled(true);
By:
getWebClient().getOptions().setCssEnabled(true);
And:
HtmlElement console = getHtmlPage().getElementById("xava_console");
By:
HtmlElement console = getHtmlPage().getHtmlElementById("xava_console");
And many more things. Unfortunately, HtmlUnit team refactor their library in each new minor version, so HtmlUnit is never backward compatible.

Migration from OpenXava 5.0.x to OpenXava 5.1

@DefaultValueCalculator dependent on other properties changes its behavior

If you have a default calculator like this one:
@DefaultValueCalculator(
    value=UnitPriceCalculator.class,
    properties=@PropertyValue(
        name="productNumber",
        from="product.number")
)
private BigDecimal unitPrice;
With versions previous to 5.1 when product.number changes unitPrice is recalculated only if it has not value yet. Since version 5.1 unitPrice is recalculated always that product.number changes.
This new behavior is more natural, so if you do not change anything your user just will have a better behavior for his applications. Anyways, maybe you want that the value would be calculated only the first time, just like before. In this case you should rewrite your logic using @OnChage, that is you should change the above code by this:
@OnChange(OnChangeProductRecalculateUnitPriceAction.class)
private Product product;
 
private BigDecimal unitPrice;

Migration from OpenXava 4.9.1 to OpenXava 5.0

User login affects your jUnit tests

Now it's required that the user signs in before executing a module so your current jUnit tests will fail. To solve this disable the login mechanism adding the next entries to your naviox.properties file in properties folder:
autologinUser=admin
autologinPassword=admin
In this way your tests will run fine without recode them.
Another option is to leave the login mechanism active and to add the login logic in your test:
public void testMyTest() throws Exception {
    login("admin", "admin");
    ...
}

Executing standalone modules is no longer available by default

When you go to /MyApplication/modules/MyModule with your browser, the module is shown with menus and login included. This is not a problem at all, because the menus are very lightweight and login can be disable with autologinUser and autologinPassword in naviox.properties. Moreover, inside Liferay the modules work as usual.
But if for some reason you prefer to work in the old way you can deactivate login and menus and use the old visual style for your modules in OpenXava 5. To do it edit the web.xml file of OpenXava project and remove:
<filter>
    <filter-name>naviox</filter-name>
    <filter-class>com.openxava.naviox.web.NaviOXFilter</filter-class>
</filter>
 
<filter-mapping>
    <filter-name>naviox</filter-name>
    <url-pattern>*.jsp</url-pattern>
</filter-mapping>
 
<filter-mapping>
    <filter-name>naviox</filter-name>
    <servlet-name>naviox</servlet-name>
</filter-mapping>
 
<filter-mapping>
    <filter-name>naviox</filter-name>
    <servlet-name>module</servlet-name>
</filter-mapping>
Also change:
<servlet>
    <servlet-name>naviox</servlet-name>
    <servlet-class>com.openxava.naviox.web.NaviOXServlet</servlet-class>
</servlet>
By:
<servlet>
    <servlet-name>modules</servlet-name>
    <servlet-class>org.openxava.web.servlets.ModuleServlet</servlet-class>
</servlet>
And change:
<servlet-mapping>
    <servlet-name>naviox</servlet-name>
    <url-pattern>/modules/*</url-pattern>
</servlet-mapping>
By:
<servlet-mapping>
    <servlet-name>modules</servlet-name>
    <url-pattern>/modules/*</url-pattern>
</servlet-mapping>
Finally remove:
<servlet-mapping>
    <servlet-name>naviox</servlet-name>
    <url-pattern>/m/*</url-pattern>
</servlet-mapping>
With the above changes in OpenXava/web.xml you have removed the menus and login. You must execute updateOX ant target to update the web.xml of your project.
For using the visual style of OpenXava 4 add the next entries to xava.properties of your project:
styleClass=org.openxava.web.style.Liferay51Style
styleCSS=liferay51/css/everything_unpacked.css

iPad native style is not used by default

When you access to an OpenXava 5 application from an iPad the style is the same of the desktop browser, the iPad native style is not shown by default. This is because iPad style only works with standalone modules, that OpenXava 5 does not use by default. If you want to use the native iPad style just follow the above instructions in section Executing standalone modules is no longer available by default to enable standalone modules.
About the support for iPad and tablets we're going to have an unique style that works fine in both desktop and tablet, a responsive style.

Transient classes require an explicit module declaration

For example, if you have a transient class called FilterByMonth with a controller called FilterByMonth and you try the URL /MyApplication/modules/FilterByMonth, it does not work until you declare it in application.xml as following:
<module name="FilterByMonth">
    <model name="FilterByMonth"/>
    <controller name="FilterByMonth"/>
</module>
Anyways, always it has been needed to declare the modules for transient classes in order to generate portlets, therefore if you work with portals you already have the modules defined.

FINEST log level produces a lot of trace

Until now FINEST log level produced a small amount of trace, but since v5.0 OpenXava generates a lot of trace with FINEST. Therefore you have to edit your xava.properties file and change:
javaLoggingLevel=FINEST
By:
javaLoggingLevel=FINE
If you want to keep a moderate amount of trace.
Until v4.9.1 the OpenXava projects created from OpenXavaTemplate had FINEST configured by default, since v5.0 they have FINE.

Objects class from org.openxava.util removed

This class conflicts with the java.util.Objects class of Java 7. Instead of qualifying the class everywhere we prefer to rename it to XObjects. In your code just replace Objects by XObjects, as following:
Objects.execute(myObject, "doSomething");
Instead now you have to write:
XObjects.execute(myObject, "doSomething");

AccessTracking removed from the distribution

You can continue using AccessTracking without any problem, just execute the updateOX ant target from AccessTracking after updating OpenXava.

URL used by ModuleTestBase includes a parameter by default

This only affects you if you overwrite getModuleURL() to add parameters. In that case just change ? by &:
public class MyModuleTest extends ModuleTestBase {
 
    ...
 
    @Override
    protected String getModuleURL() {
        // return super.getModuleURL() + "?myParameter=5"; // With ? in v4.x.x
        return super.getModuleURL() + "&myParameter=5"; // With & in v5.0
    }
}

@Digits annuls default scale

When @Digits is specified default scale is ignored even if fraction is not specified. It means that if you write:
@Digits(integer=10)
private BigDecimal amount;
With v4.x it had 2 fraction digits because default scale for BigDecimal is 2. However, since v5.0 it has 0 digits, because not specifying fraction is equals to write fraction=0. This allows you to have BigDecimal numbers with 0 for fraction part, but it could do than some of your existing numeric properties stop to use 2 fraction digits. To fix it, just specify fraction explicitly, thus:
@Digits(integer=10, fraction=2)
private BigDecimal amount;

BigDecimal formatting fixed (for jUnit tests)

Scale defined in default-size.xml and from @Column and @Digits was ignored when formatting. We fixed it. Yes, the number formatting works better, but you have to adapt your tests. For example, if you use a BigDecimal with no annotations you should change:
assertValue("myBigDecimalNumber", "20");
by this:
assertValue("myBigDecimalNumber", "20.00");

Migration from OpenXava 4.9 to OpenXava 4.9.1

Method getFrame() access modifier changed

The access modifier of the method getFrame() in org.openxava.web.style.Style was changed from protected to public. If you have classes which overrides getFrame(), then you are required to change its access modifier from protected to public.

Migration from OpenXava 4.8.1 to OpenXava 4.9

PDF report headers can use several lines

This does not affect your application code at all. However, if you verify the PDF content in your automatic tests maybe you need to make some adjustments. For example, the next code would fail if the header of the report now use 2 lines instead of 1:
assertPopupPDFLinesCount(5); // Maybe now there are 6 lines, because the header uses 2 lines

CustomReport controller renamed to MyReport

It's unlikely that you need to change your code at all, because this is a controller for internal use of 'My reports' dialog and available only since OpenXava 4.6. However, if you have used actions of CustomReport controller in your jUnit tests you have to rename them to MyReport.

Migration from OpenXava 4.8 to OpenXava 4.8.1

Hidding a member whose name is the same of its container section

We have fixed View.setHidden() to work with sections too, it already worked with groups but not with sections. Therefore, if you have a view like this one:
@View(members=
  ...
  "remarks { advice, shortcut; remarks }"
  ...
)
Where the remarks property is inside a remarks section. Until now if you write this:
getView().setHidden("remarks", true);
You hid the remarks property, however since OpenXava 4.8.1 you'll hide the remarks section. In this case, if you still want to hide the property and not the section you should rename the section, as following:
@View(members=
   ...
   "comment { advice, shortcut; remarks }"
   ...
)

Migration from OpenXava 4.7.1 to OpenXava 4.8

No issues.

Migration from OpenXava 4.7 to OpenXava 4.7.1

Gallery.return action renamed to Gallery.close

This is because Gallery editor now uses a dialog instead of a plain view. Moreover, the controller for read only Gallery is Close instead of Return. It's unlikely that you need to change your code at all. However, if you have used this action in jUnit tests you will need to rename it.

Migration from OpenXava 4.6.1 to OpenXava 4.7

Action ExtendedPrint.customReport renamed to ExtendedPrint.myReports

It's unlikely that you need to change your code at all, because this is an action from Typical (so always present) and available only since OpenXava 4.6. However, if you have used this action in jUnit tests, @Action or IChainAction, you will need to rename it.

Method getSelected() of Tab and TabBaseAction deprecated, now we will use getSelectedKeys()

The getSelected() method of Tab and TabBaseAction has been deprecated, instead we have getSelectedKeys(), this method return the keys (Map) from the selected elements.
In most cases getSelected() works well, but if there are some row out of the range of load rows it malfunctions. E.g.: first we select a row, afterwards we order by any column and then we leave this row out of the range of loaded rows. If we use getSelected() we don't get this row, but using getSelectedKeys() we do it.
We have to change in our code:
int[] selected = tab.getSelected();
for (int i = 0; i < selected.length; i++){
     Map key = (Map) tab.getTableModel().getObjectAt(selected[i]);
     ....
}
by:
Map[] selected = tab.getSelectedKeys();
for (int i = 0; i < selected.length; i++){
     Map key = selected[i];
     ....
}

Migration from OpenXava 4.6 to OpenXava 4.6.1

Messages in i18n files with no arguments are formatted in the standard way

Really this is a bug fix, but it can affect your i18n messages if they contain apostrophes, so you have to change:
my_message=It can't be in that way
by
my_message=It can''t be in that way
Note, you have to change ' by ''.

Migration from OpenXava 4.5.1 to OpenXava 4.6

No issues.

Migration from OpenXava 4.5 to OpenXava 4.5.1

Custom editors must specify tabindex attribute

In order to be in the correct tab order the editors must specify tabindex="1" in its HTML code, thus:
<input id="<%=propertyKey%>"
    name="<%=propertyKey%>" class="<%=style.getEditor()%> <%=numericClass%>"
    type="<%=inputType%>"
    tabindex="1" <!-- Now, you have put this-->
    ...
/>

Migration from OpenXava 4.4.x to OpenXava 4.5

Pure select in baseCondition of @Tab now must use JPQL syntax and not SQL

Since v4.5 OpenXava uses JPA to obtain tabular data, before it used SQL. It means that when you use baseCondition to write the complete select you have to use the JPQL syntax, SQL is no longer supported.
That is, if your select is like this one:
baseCondition =
    "select NUMBER, DESCRIPTION, FAMILY.DESCRIPTION " +
    "from   XAVATEST.SUBFAMILY, XAVATEST.FAMILY " +
    "where  SUBFAMILY.FAMILY = FAMILY.NUMBER"
You have to rewrite it in this way:
baseCondition =
    "select e.number, e.description, f.description " +
    "from Subfamily e, Family f " +
    "where e.familyNumber = f.number"
The syntax of JPQL and SQL is very alike, usually you will not need to do big changes other that using property and entity names intestad of column and table names. You have to use e as alias for the main entity.

The condition of @DescriptionsList now uses JPQL syntax and not SQL

Since v4.5 OpenXava uses JPA to obtain the data for the combos, so you have to use JPQL syntax in condition. If you use not too complicated conditions and use ${propertyName} instead of column name, surely you do not need to do any change. However, maybe you need to do some change, specially if you use column names. For example, the next code no longer work:
@DescriptionsList(
    // It does not works because THINGID is a column name, so JPA does not recognized it
    condition="${thing.number} = (SELECT THINGID FROM ${Thing} WHERE name = 'CAR')"
)
The solution is using property names instead of column names, in this case changing THINGID by number is enough to fix the problem:
@DescriptionsList(
    // It works because we use the property name, number, instead of THINGID
    condition="${thing.number} = (SELECT number FROM ${Thing} WHERE name = 'CAR')"
)
Another option is to write the complete sentence in pure JPQL, given that the ${} are no longer required, as following:
@DescriptionsList(
    // We can use a pure JPQL query without ${propertyName}
    condition="e.thing.number = (SELECT t.number FROM Thing t WHERE t.name = 'CAR')"
)
If you use JPQL you have to use e as alias for the main entity.

@OnSelectElementAction does not refresh by default its collection

This new behavior produces a much better performance in many cases, specially when you are working with huge collection and selecting an elements does not change the collection data. However, if you have a case when your @OnSelectElementAction changes the collection content you have to refresh the collections explicitly, as following:
public class MyOnSelectElementAction extends OnSelectElementBaseAction {
 
    public void execute() throws Exception {
        doSomethingThatModifiesTheCollection();
        getView().refreshCollections(); // Since v4.5 you have to add this line
    }
 
}

Migration from OpenXava 4.3.x to OpenXava 4.4

HtmlUnit upgraded from 2.5 to 2.9

HtmlUnit is the library used to simulate a browser from the jUnit tests. It has been upgraded to 2.9 version. HtmlUnit has renamed and dropped some methods and classes, indeed they are always refactoring their library (refactoring is good for applications but not so good for libraries). Probably you do not need to change anything in your jUnit tests because ModuleTestBase hides HtmlUnit, however if you are using the HtmlUnit API directly, using getHtmlPage() from ModuleTestBase for example, maybe you have to adapt some method calls.

Migration from OpenXava 4.2.x to OpenXava 4.3

No issues.

Migration from OpenXava 4.1.x to OpenXava 4.2

No issues.

Migration from OpenXava 4.0.1 to OpenXava 4.1

New action in list and collections (for junit tests)

The list and collections have a new action available for the users (List.sumColumn), therefore if you test for all present actions in your junit tests, you need to modify it in order to take into account the new List.sumColumn action:
private String [] listActions = {
"Mode.detailAndFirst",
"Mode.split",
"List.filter",
"List.customize",
"List.orderBy",
"List.viewDetail",
"List.hideRows",
"List.sumColumn" // ADD THIS ENTRY
};
assertActions(listActions);

Migration from OpenXava 4.0 to OpenXava 4.0.1

There is not default converter for boolean

From now on there is not a default converter defined in default-converters.xml for java.lang.Boolean and boolean. Really, this does not produce any incompatibility problem in JPA applications, since in these applications the JPA engine does the conversion itself. However, if you have a old XML application, you only have to regenerate the code and everything will work fine, because most database do a good job translating boolean to numeric automatically. Anyways, you can configure your application in order that it works as before, just add the following lines to the converters.xml file in the xava folder of your application:
<for-type type="boolean"
converter-class="org.openxava.converters.Boolean01Converter"
cmp-type="java.lang.Integer"/>
 
<for-type type="java.lang.Boolean"
converter-class="org.openxava.converters.Boolean01Converter"
cmp-type="java.lang.Integer"/>
Remember, adding these lines is rarely necessary, regenerating code must be enough. If you application is a JPA application (the usual case) you do not need to do anything.

Migration from OpenXava 4m6 to OpenXava 4.0

No issues.

Migration from OpenXava 4m5 to OpenXava 4m6

Hibernate updated to Hibernate 3.6

In OpenXava 4m6 the Hibernate engine has been upgraded to Hibernate 3.6 in order to support JPA 2.0. Most of the code works with no modification. However, there are some details maybe you have to modify in your code. Below you will find some of those details.
Additionally, it's hightly advisable that you undeploy your old application from the application server, and deploy it again. That is, delete the old application from webapps folder of Tomcat, before deploying a new version of your application based on OX4m6, thus you will be sure that the old JPA and Hibernate jars are removed. Also remove the .dist folders from your workspace or workspace.dist.

Nonexistent @ManyToOne references used as @Id are no longer supported (Hibernate 3.6)

Hibernate 3.6 does not support nonexistent @ManyToOne references used as @Id. That is, if you have an entity with the next ids:
public class Delivery {
 
@Id @Column(length=5)
private int number;
 
@Id @ManyToOne(fetch=FetchType.LAZY)
private DeliveryType type;  // The type must exist in the database always
...
}
The reference to DeliveryType must exist always in the database.
Really, this is a very rare case that you will only face when working against legacy databases designed by programmers of the pre-RDBMS era (like RPG programmers). They sometimes use composite keys that include references to other tables, and when the reference does not exist they put zeroes in the fields. If you face this case you can solve it in some of the next ways:
  • Create a row in the reference table with 0 as key.
  • Use a plain property instead of a reference. In this case you can use some special editor for the property.
  • Allow nulls for the column used as pseudo-foreign-key and change all the zeroes by nulls for that column.

In order to assign an already existing entity to a reference it must be managed (Hibernate 3.6)

That is, in previous versions of Hibernate, you could write:
Delivery delivery = new Delivery();
DeliveryType deliveryType = new DeliveryType(); // We create a new DeliveryType,
// instead of searching it
deliveryType.setNumber(66); // The DeliveryType 66 already exist in database
delivery.setType(deliveryType);
...
XPersistence.getManager().persist(delivery);
But, this does not work with Hibernate 3.6, instead you have to write it in the next way:
Delivery delivery = new Delivery();
DeliveryType deliveryType = XPersistence.getManager()
.find(DeliveryType.class, 66); // We searh it
delivery.setType(deliveryType);
XPersistence.getManager().persist(delivery);

Entity with only one @ManyToOne reference as key (Hibernate 3.6)

With previous versions of Hibernate you could write the next code in your entity:
@Entity
@IdClass(CustomerContactPersonKey.class)
public class CustomerContactPerson {
 
@Id @ManyToOne(fetch=FetchType.LAZY)
private Customer customer;
 
// No more @Id fields
 
...
 
}
And the reference to it in this way:
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="CUSTOMERCONTACT") // With no referencedColumnName attribute
private CustomerContactPerson customerContactPerson;
And it worked fine. However, with Hibernate 3.6 this does not work. Fortunately, there is a way of achieving the same effect. Just write your entity in this way:
@Entity // @IdClass is no longer used
public class CustomerContactPerson
implements java.io.Serializable { // Must implement Serializable
 
@Id @ManyToOne(fetch=FetchType.LAZY)
private Customer customer;
 
// No more @Id fields
 
...
 
}
And the reference in this way:
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumns({
@JoinColumn(name="CUSTOMERCONTACT",
referencedColumnName="CUSTOMER_NUMBER") // referencedColumnName is mandatory
})
private CustomerContactPerson customerContactPerson;

CharBooleanType Hibernate type does not work (Hibernate 3.6)

CharBooleanType type (and some other Hibernate types) has been deprecrated, even more, they do not work fine in Hibernate 3.6. If you have a type that extends from CharBooleanType, you must rewrite it extending AbstractSingleColumnStandardBasicType. See the SiNoType in org.openxava.types package.

Discriminator throws duplicate Id (Hibernate 3.6)

Entities used for table per class inheritance using discriminator which field is also an @Id, will throw a duplicate id error. Suppose that you have an entity description like this case:
@Entity
@Table(name = "`TABLES`")
@DiscriminatorColumn(name="ID",
discriminatorType=DiscriminatorType.STRING,
length=20)
 
This would work without problem in 3.4, but will complain in 3.6 (and I believe in 3.5 too). You have to use a Hibernate annotation @DiscriminatorOptions like this:
@Entity
@Table(name = "`TABLES`")
@DiscriminatorColumn(name="ID",
discriminatorType=DiscriminatorType.STRING,
length=20)
@DiscriminatorOptions(insert = false) // <-- Hibernate dependent annotation
 
And it will work.

Method getProperty() renamed in ModuleTestBase

Method getProperty() of ModuleTestBase has been renamed to getXavaJUnitProperty(). So, if you use it in your test you have to rename the method calls, as following:
String host = getProperty("host"); // Until v4m5
// Must be replace with
String host = getXavaJUnitProperty("host"); // Since v4m6
This change was needed to allow using Groovy to write JUnit tests.

Migration from OpenXava 4m4 to OpenXava 4m5

Navigation controller is not added automatically

Until now Navigation controller (with the previous - home - next actions in detail mode) was added automatically to all modules with detail and list. From now on, this controller is no longer added implicitly. This is not a problem since Typical extends it, but if you have a detail - list module with no Typical controller, then you have to add Navigation explicitly:
<module name="ChangeProductsPrice">
<model name="Product"/>
<controller name="Navigation"/>  <!-- You have to add this -->
<controller name="ChangeProductsPrice"/>
</module>

New split mode - jUnit changes

In addition to detail and list, now we have a new mode, split, that allows to show the list and the detail at the same time. This feature does not produce any incompatibility at application level, but if you use assertActions() in your tests maybe you have to add this new action:
String [] listActions = {
"Print.generatePdf",
"Print.generateExcel",
"CRUD.new",
"CRUD.deleteSelected",
"Mode.detailAndFirst",
"Mode.split", // YOU HAVE TO ADD THIS
"List.filter",
"List.customize",
"List.orderBy",
"List.viewDetail",
"List.hideRows",
};
assertActions(listActions);
If you do not like this new split mode, you can remove it from your aplication adding the next entry in xava.properties:
defaultModeController=DetailList
In this case the mode controller is not Mode but DetailList, this implies that you have to change your junit tests:
// execute("Mode.list"); // NO if defaultModeController=DetailList in xava.properties
execute("DetailList.list"); // OK if defaultModeController=DetailList in xava.properties

New CRUD.deleteRow action - jUnit changes

The CRUD.deleteSelected action has been split into CRUD.deleteSelected and CRUD.deleteRow. If you used CRUD.deleteSelected with row argument, you have to change it by CRUD.deleteRow:
// execute("CRUD.deleteSelected", "row=2"); // NO, since 4m5
execute("CRUD.deleteRow", "row=2"); // YES
Moreover, given that CRUD.deleteRow is available by default for all module, if you use assertActions() in your tests maybe you have to add it to the list of actions.

View is not editable by default

From now on when a module is initialized the View object is not editable. This is no big deal because the new and search actions set the correct editable state of the view. But if you have a custom new or search action maybe you have to modify them to set the editable state explicitly:
public class MySearchAction extends ViewBaseAction {
 
public void execute() throws Exception {
...
getView().setKeyEditable(false);  // You have to call setKeyEditable()
getView().setEditable(true);      // and setEditalbe() explicitly
...
}
 
}

Migration from OpenXava 4m3 to OpenXava 4m4

CRUD.search now uses a dialog - jUnit changes

The CRUD.search action now uses a dialog to entry the search data. This means that all your junit tests that uses CRUD.search will fail. That is, if you have a test like the next one:
setValue("number", "1");
execute("CRUD.search");
assertValue("description", "Number one");
It does not work now. You must rewrite it. To do it, you have 2 options. The first one is to adapt your test to the new CRUD.search action behavior:
execute("CRUD.search"); // It shows a dialog
setValue("number", "1");
execute("Search.search"); // It does the search and close the dialog
assertValue("description", "Number one");
The second option is changing "CRUD.search" by "CRUD.refresh", since the old CRUD.search has been renamed as CRUD.refresh:
setValue("number", "1");
execute("CRUD.refresh"); // Instead of CRUD.search
assertValue("description", "Number one");
Moreover, given that CRUD.refresh is available by default for all modules, if you use assertActions() in your tests maybe you have to add it to the list of actions.

Migration from OpenXava 4m2 to OpenXava 4m3

MapFacade.getValues() includes the model name in the result

MapFacade.getValues() now includes the model name in the result, with an entry with the key MapFacade.MODEL_NAME. If you use the standard OpenXava classes (such as View or PropertiesManager) everything will work fine, but if you have your custom code maybe it fails because this new unexpected entry. In this case you have to remove the entry from the values, in this way: