openxava / documentación / Migración a v6.x

Si quieres migrar a 7.0 o superior mira las instrucciones de migración nuevas

¿Cómo actualizar tu proyecto a la última versión de OpenXava 6.x?


Para migrar de OpenXava 6.6.2 a OpenXava 6.6.3

No hay consideraciones.

Para migrar de OpenXava 6.6.1 a OpenXava 6.6.2

No hay consideraciones.

Para migrar de OpenXava 6.6 a OpenXava 6.6.1

No hay consideraciones.

Para migrar de OpenXava 6.5.3 a OpenXava 6.6

No hay consideraciones.

Para migrar de OpenXava 6.5.2 a OpenXava 6.5.3

No hay consideraciones.

Para migrar de OpenXava 6.5.1 a OpenXava 6.5.2

Cuatro dígitos para año en todos los idiomas (para las pruebas JUnit)

Hasta ahora usábamos cuatro dígitos para el año sólo para algunos idiomas. A partir de ahora usaremos cuatro dígitos para el año en todos los idiomas. Por lo que, si usas un idioma que usaba dos dígitos para el año (como inglés por ejempo) has de ajustar tus pruebas JUnit, cambiando, por ejemplo, esto:
assertValue("date", "5/25/21");
Por esto:
assertValue("date", "5/25/2021");
Fíjate como hemos cambiado 21 por 2021.

Para migrar de OpenXava 6.5 a OpenXava 6.5.1

No hay consideraciones.

Para migrar de OpenXava 6.4.2 a OpenXava 6.5

Sólo las consultas grabadas explícitamente se recuerdan en modo lista (para las pruebas JUnit)

En v6.5 sólo las consultas grabadas explícitamente se almacenan en modo lista, por tanto las pruebas JUnit que confiaban en esto para reutilizar un filtro usado previamente fallarán. Es decir, este código ahora falla:
setConditionValues("1");
execute("List.filter"); // Esto no graba "Código = 1" automáticamente

// Aquí haces más cosas

selectListConfiguration("Código = 1"); // FALLA EN v6.5
La solución es grabar la consulta explícitamente, así:
setConditionValues("1");
execute("List.filter"); 

execute("List.saveConfiguration"); // AÑADE ESTAS LÍNEAS PARA GRABAR...
execute("SaveListConfiguration.save"); // ...LA CONSULTA EXPLÍCITAMENTE

// Aquí haces más cosas

selectListConfiguration("Código = 1"); // Ahora funciona

Acción para cambiar el nombre de la consulta no disponible para la consulta 'Todos' (para las pruebas JUnit)

Dado que sólo las consultas grabadas explícitamente se almacenan en modo lista, sólo las consultas grabadas explícitamente se pueden renombrar o quitar. Además, la consulta 'Todos' no se puede renombrar ni quitar. Estos cambios no requieren que modifiques el código de tu aplicación. Sin embargo, tienes que adaptar tus prueba JUnit a la nueva interfaz de usuario, porque cuando entras en un módulo en modo lista, normalmente la consulta 'Todos' se muestra inicialmente, y por tanto la acción para Cambiar nombre/quitar (List.changeConfiguration) ya no está ahí. Por lo tanto, si usas assertActions() en tus pruebas deberías adaptar tu lista de acciones, quitando List.changeConfiguration, así:
String [] acciones = {
    "Print.generatePdf",
    "Print.generateExcel",
    "ImportData.importData", 
    "CRUD.new",
    "CRUD.deleteSelected",
    "CRUD.deleteRow",
    "List.filter",
    "List.orderBy",
    "List.viewDetail",
    "List.hideRows",
    "List.sumColumn",
    // "List.changeConfiguration", // QUITA ESTA LÍNEA
    "List.changeColumnName", 
    "ListFormat.select" 
}; 
assertActions(acciones);

Para migrar de OpenXava 6.4.1 a OpenXava 6.4.2

No hay consideraciones.

Para migrar de OpenXava 6.4 a OpenXava 6.4.1

No hay consideraciones.

Para migrar de OpenXava 6.3.2 a OpenXava 6.4

Modificar el Deployment Assembly para ejecutar Tomcat dentro de Eclipse

Si todavía ejecutas Tomcat dentro de Eclipse con Eclipse IDE for Enterprise Java Developers, has de modificar el Deployment Assembly de tu proyecto para no incluir OpenXava y Addons como proyectos dependientes. Para eso, dentro de Eclipse pulsa con el botón derecho del ratón, y escoge Properties > Deployment Assembly, entonces te saldrá un diálogo como este:
Ahí selecciona Addons y OpenXava, y pulsa el botón Remove. Después pulsa Apply and Close.

Etiqueta automática para miembro de referencia en lista mejorada (para pruebas JUnit)

Las etiquetas automáticas para miembros de referencias ahora hacen la primera letra mayúscula y todas las demás minúsculas. Esto no afecta al código de tu aplicación, pero si verificas las etiquetas de alguna lista puede que tengas que hacer algún ajuste en tus pruebas JUnit, como cambiar este assert::
assertLabelInList(0, "Year of Invoice");
Por este otro:
assertLabelInList(0, "Year of invoice");

Para migrar de OpenXava 6.3.1 a OpenXava 6.3.2

No hay consideraciones.

Para migrar de OpenXava 6.3 a OpenXava 6.3.1

Al cerrar el diálogo no se pierde la paginación de la colección (para pruebas JUnit)

En realidad esto es un arreglo, pero si tus pruebas JUnit confían en este fallo, has de adaptarlas. Por ejemplo, en el siguiente código JUnit deberías quitar la segunda acción de paginación:
execute("List.goNextPage", "collection=miColeccion");
execute("Collection.edit", "row=10,viewObject=xava_view_miColeccion");
setValue("nombre", "Nombre modificado");
execute("Collection.save");
// execute("List.goNextPage", "collection=miColeccion"); // QUITA ESTA LÍNEA
assertValueInCollection("miColeccion", 0, 0, "Nombre modificado");
Porque ahora después de cerrar el diálogo la colección pemanece in la misma página, por lo que ya no necesitas reposicionarla.

Para migrar de OpenXava 6.2.2 a OpenXava 6.3

Página de bienvenida para Internet Explorer

Hemos movido los colores a variables CSS. Las variables no se soportan en Internet Explorer 11, por suerte es muy fácil añadir soporte de variables CSS a IE11 usando una librería JS. Lo hemos hecho para todo el código de OpenXava, pero la página de bienvenida (welcome.jsp) es tuya, por lo que has de añadir el siguiente código a welcome.jsp para que pueda usar los estilos de OpenXava bien con IE9:
<% if (org.openxava.web.Browsers.isIE(request)) { %>
<script type='text/javascript' src="<%=request.getContextPath()%>/xava/js/css-vars-ponyfill.js?ox=<%=oxVersion%>"></script>
<script type='text/javascript'>cssVars({ }); </script>	
<% } %>

Página de bienvenida para el contexto raíz

Desde v6.3 puedes ejecutar tu aplicación en el contexto raíz, es decir sin usar el nombre de la aplicación en la URL. Todo el código de OpenXava ha sido adaptado para esto, pero la página de bienvenida (welcome.jsp) es tuya, por lo que tienes que cambiar el siguiente código en welcome.jsp:
String applicationName = request.getContextPath().substring(1);
MetaApplication metaApplication = MetaApplications.getMetaApplication(applicationName);
Por:
MetaApplication metaApplication = MetaApplications.getMainMetaApplication();
Esto es sólo necesario si quieres que tu aplicación funcione en el contexto raíz.

Para migrar de OpenXava 6.2.1 a OpenXava 6.2.2

No hay consideraciones.

Para migrar de OpenXava 6.2 a OpenXava 6.2.1

No hay consideraciones.

Para migrar de OpenXava 6.1.2 a OpenXava 6.2

Definición de fuentes de datos en web/META-INF/context.xml del proyecto

Por tanto, si haces un actualizarOX en tu proyecto y lo pruebas en un Tomcat dentro de Eclipse, te fallará. Ahora has de definir tu fuente de datos en web/META-INF/context.xml de tu proyecto. Esta es la fuente de datos para usar en desarrollo, en producción (es decir en Tomcat fuera de Eclipse) las fuentes de datos definidas en conf/context.xml del Tomcat tienen preferencia, por lo que no tienes que cambiar las fuentes de datos en producción, sólo en desarrollo.

Nuevo editor para los estereotipos FOTO, IMAGEN, GALERIA_IMAGENES, ARCHIVO y ARCHIVOS (para pruebas JUnit)

El nuevo editor no requiere ningún cambio en el código de la aplicación, pero dado que las acciones de los controladores ImageEditor, Gallery, LoadImageIntoGallery, etc. ya no existen deberías adaptar las pruebas donde subes archivos. Por ejemplo, si tienes este código de prueba para cargar una imagen:
execute("ImageEditor.changeImage", "newImageProperty=imagen"); 
String urlImagen = System.getProperty("user.dir") + "/imagenes-pruebas/pastel.gif";
setFileValue("newImage", urlImagen);
execute("LoadImage.loadImage");
Deberías reescribirlo así:
uploadFile("imagen", "imagenes-pruebas/pastel.gif");
Para el caso de la galería:
execute("Gallery.edit", "galleryProperty=fotos");
execute("Gallery.addImage");
String urlImagen = System.getProperty("user.dir") + "/imagenes-pruebas/foto-javi.png";
setFileValue("newImage", urlImagen);
execute("LoadImageIntoGallery.loadImage");
execute("Gallery.close");
Deberías reescribirlo así:
uploadFile("fotos", "imagenes-pruebas/foto-javi.png");
Lo mismo para los estereotipos ARCHIVO y ARCHIVOS. en ModuleTestBase ahora tenemos los métodos uploadFile(), removeFile(), assertFile(), assertNoFile() y assertFilesCount() para lidiar con los editors de subida de archivos.

El nuevo editor para GALERIA_IMAGENES es en línea y con marco

Por tanto ya no se visualiza como una propiedad simple, lo que significa que puede que tengas que adaptar la disposición de alguna de tus vistas. Por ejemplo, si tienes:
@View(members="numero, descripcion, pantallazos, fecha")
Donde pantallazos es una GALERAY_IMAGENES, ahora deberías reescribirlo de la siguiente manera:
@View(members="numero, descripcion; pantallazos; fecha")
Dejando una sola línea para la propiedad pantallazos.

El nuevo editor para el estereotipo ARCHIVOS llena todo el ancho de la vista

Esto implica que quizás tengas que adaptar la disposición de algunas de tus vistas. Por ejemplo, si tienes:
@View(members="numero, descripcion, adjuntos, fecha")
Donde adjuntos es una propiedad ARCHIVOS, ahora deberías reescribirla de la siguiente forma:
@View(members="numero, descripcion; adjuntos; fecha")
Dejando una sola línea para la propiedad adjuntos.
Además no deberías usar ARCHIVOS en vistas alineadas por columas (las que tienen un # antes de los miembros), es decir deberías cambiar:
@View(members=
    "datos [ #titulo;" +	
    "   fechaEstreno, director;"   +
    "   guionistas, elenco;"    +
    "   guiones;" + // ARCHIVOS
    "]"
)
Donde guiones es una propiedad ARCHIVOS, por:
@View(members=
    "datos [ #titulo;" +	
    "   fechaEstreno, director;"   +
    "   guionistas, elenco;"    +
    "]" +
    "guiones [ guiones ]"
)
Fíjate como ponemos la propiedad ARCHIVOS, guiones, en su propio grupo.

Para migrar de OpenXava 6.1.1 a OpenXava 6.1.2

No hay consideraciones.

Para migrar de OpenXava 6.1 a OpenXava 6.1.1

Primera carga de página del módulo vía AJAX (sólo si usas el API de HtmlUnit)

Ahora la primera carga de página se hace vía AJAX, por lo que si usas directamente HtmlUnit en tus pruebas has de esperar a que la petición AJAX se complete cuando cargues una página. Esto se hace llamando a waitAJAX(), de esta manera:
HtmlPage page = (HtmlPage) getWebClient().getCurrentWindow().getEnclosedPage();
waitAJAX(); // AÑADE ESTA LÍNEA ANTES DE USAR page

Si tus pruebas usan métodos de ModuleTestBase exclusivamente no has de hacer ningún cambio.

Para migrar de OpenXava 6.0.2 a OpenXava 6.1

Bean Validation actualizado de 1.1 a 2.0

Bean Validation 2.0 es compatible con 1.1, por lo que la mayoría de tu código seguirá funcionando como siempre. Sin embargo, Bean Validation 2.0 incluye algunas anotaciones nuevas que antes estaban en Hibernate Validator, por eso si importabas los dos, Hibernate Validator y Bean Validation, puede que tu código no compile. Por ejemplo:

import javax.validation.constraints.*;
import org.hibernate.validator.constraints.*; 

public class MiClase {

    // @NotBlank // AHORA COMPILA CON ERROR
@javax.validation.constraints.NotBlank // CALIFICA LA ANOTACIÓN
    private String callePrincipal;

Ahora @NotBlank está tanto en javax.validation.constraints como en org.hibernate.validator.constraints. Simplemente quita el import de org.hibernate.validator.constraints o, si todavía necesitas Hibernate Validator, califica la anotación @NotBlank (es decir usa @javax.validation.constraints.NotBlank).

Actualización de librerias EL para Tomcat 7 u otro servidor de aplicaciones antiguo

Si usas Tomcat 7 copia el-api.jar y jasper-el.jar de la carpeta lib del Tomcat incluido en OpenXava (o cualquier Tomcat 9) a la carpeta lib de tu Tomcat 7. Esto es requerido por última versión de Hibernate Validator. Si usas otro servidor de aplicaciones antiguo (como una versión vieja de WebLogic) y no sabes como actualizarlo, simplemente copia el-api.jar y jasper-el.jar a la carpeta WEB-INF/lib de tu proyecto.

HtmlUnit actualizado de 2.15 a 2.32

Si usas directamente el API de HtmlUnit, vía getWebClient() o getHtmlPage() de ModuleTestBase, tienes que adaptar tu código al nuevo HtmlUnit. Hemos recolectado aquí algunos cambios que hemos notado.

Por ejemplo, los métodos que empiezan por getHtmlElement... ahora son getElement..., sólo has de quitar el Html. Por tanto, deberías cambiar:

HtmlElement i = chartsLink.getHtmlElementsByTagName("i").get(0);

Por:

HtmlElement i = chartsLink.getElementsByTagName("i").get(0);

El método click() ya no lanza el evento onclick. Por lo que has de cambiar:

boton.click();

Por:

getHtmlPage().executeJavaScript(boton.getOnClickAttribute());

Cambiar el valor de un HtmlInput ya no lanza el evento onchange, por lo que has de cambiar:

input.setValueAttribute(valor);
Por:
input.setValueAttribute(valor);
if (!Is.emptyString(input.getOnChangeAttribute())) {
    input.fireEvent(Event.TYPE_CHANGE);
}

Y posiblemente más cosas, consulta la documentación de HtmlUnit.

ModuleTestBase.setLocale() reinicia el módulo

Por causa del nuevo HtmlUnit ya no tenemos manera de cambiar el lenguaje sin reiniciar el módulo. Por tanto, puede que necesites adaptar algunas de tus pruebas. Por ejemplo:

execute("CRUD.new");
...
setLocale("es"); // Aquí el módulo se reinicia
execute("CRUD.new"); // AÑADE ESTA LÍNEA
...

En este caso el setLocale() reinicia el módulo empezando en modo lista, por eso llamamos a CRUD.new, para que la prueba continue funcionando como siempre.

Hibernate actualizado de 4.3 a 5.3

Dado que usamos el API de JPA en nuestras aplicaciones la mayoría de nuestro código debería funciona sin ningún cambio. Sin embargo, puede que encuentres algún detalle que funcione ligeramente diferente. Por ejemplo, para esta definición de entidad:

public class Cliente {
    @OneToMany
    private Collection<Vendedor> vendedores;

El siguiente código ha dejado de funcionar:

cliente.setVendedores(Collections.emptySet());
Ahora has de escribir:
cliente.setVendedores(new ArrayList<>());

Quizás encuentres alguna que otra cosa que tengas que ajustar, consulta la documentación de Hibernate. De todos modos, en los puntos que siguen explicamos los cambios más importantes relacionados con Hibernate 5.3.

Claves foráneas duplicadas si se usa generación automática de esquema

Hibernate 5.3 tiene un bug que duplica las claves foráneas si usas hibernate.hbm2ddl.auto=update contra la base de datos que estabas usando con Hibernate 4.3. Si tu base de datos es tolerante con las claves duplicadas no hay problema, en caso contrario puede que tengas algunas advertencias e incluso errores. De momento, la única solución a esto es quitar todas las claves foráneas de tu base de dato manualmente, de tal forma que Hibernate las cree correctamente al arrancar.

Actualizar esquema automáticamente al arrancar requiere un esquema por defecto

En Hibernate 5.3 la siguiente configuración para persistence.xml no funciona:

<properties>
    <property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>

Has de definir un hibernate.default_schema para que vaya. Si no usas un esquema simplemente define el esquema por defecto para tu base de datos, por ejemplo PUBLIC para HSQLDB, así:

<properties>
    <property name="hibernate.hbm2ddl.auto" value="update"/>
    <property name="hibernate.default_schema" value="PUBLIC"/>
</properties>
Por otra parte, la tarea ant actualizarEsquema funciona perfectamente incluso sin definir esquema.

MySQL ya no reconoce el esquema por defecto

Con Hibernate 5.3 hibernate.default_schema ya no tiene efecto en MySQL, ahora has de usar hibernate.default_catalog en su lugar. A partir de OpenXava 6.1.2 hemos modificado la API de OpenXava para que funcione como siempre, reconociendo hibernate.default_schema incluso para MySQL. Sin embargo, la generación automática de esquema al iniciar la aplicación (es decir hibernate.hbm2dll.auto=update o javax.persistence.schema-generation.database.action=update) es asunto de Hibernate, por lo que no podemos arreglarlo. Si usas esta funcionalidad, deberías cambiar hibernate.default_schema por hibernate.default_catalog.

Resumiendo, si usas MySQL cambia en persistence.xml:

<properties>
    <property name="hibernate.hbm2ddl.auto" value="update"/>
    <property name="hibernate.default_schema" value="EMPRESAB"/>
</properties>

Por:

<properties>
    <property name="hibernate.hbm2ddl.auto" value="update"/>
    <property name="hibernate.default_catalog" value="EMPRESAB"/>
</properties>

Fíjate, hibernate.default_catalog en vez de hibernate.default_schema. Sólo para MySQL.

@GeneratedValue(strategy=GenerationType.AUTO) ya no es IDENTITY por defecto

En Hibernate 5.3 @GeneratedValue(strategy=GenerationType.AUTO) ya no es IDENTITY por defecto, al menos para HSQLDB. Por tanto, si usas HSQLDB y no quieres cambiar tu estructura de tablas has de cambiar:

@Id 
@GeneratedValue(strategy=GenerationType.AUTO) // O @GeneratedValue a secas private int id;

Por esto:

@Id 
@GeneratedValue(strategy=GenerationType.IDENTITY) private int id;

En tus propiedades id con GenerationType.AUTO.

Definición de métodos cambiada para UserType y CompositeUser de Hibernate

En Hibernate 5.3 han cambiado la definición de los métodos para los conversores de tipo, los que se usan en la anotación @Type. Si has creado tu propio conversor de tipo Hibernate has de hacer algunas ligeras modificaciones en la definición de tus métodos, concretamente has de cambiar SessionImplementer por SharedSessionContractImplementor como parámetro. Por ejemplo, deberías cambiar esta línea:

public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor sessionImplementor, Object owner) 
    throws HibernateException, SQLException {

Por esta otra:

public Object nullSafeGet(ResultSet resultSet, String[] names, SharedSessionContractImplementor sessionImplementor, Object owner)
    throws HibernateException, SQLException {

Lo mismo para todos los métodos que usen SessionImplementer en cualquier implementación de UserType o CompositeUser.

Configuración para Liferay

Para que el nuevo Hibernate 5.3 funcione con Liferay has de crear un archivo portal-ext.properties en la carpeta webapps/ROOT/WEB-INF/classes del Tomcat en tu Liferay, con la siguiente entrada:

portal.security.manager.strategy=none           

Para migrar de OpenXava 6.0.1 a OpenXava 6.0.2

No hay consideraciones.

Para migrar de OpenXava 6.0 a OpenXava 6.0.1

No hay consideraciones.

Para migrar de OpenXava 5.9.1 a OpenXava 6.0

Nuevas páginas de bienvenida y de primeros pasos

Si no has modificado tus página de bienvenida y primeros pasos has de borrar web/naviox/welcome.jsp y web/naviox/firstSteps.jsp de tu proyecto antes de hacer el actualizarOX. Si tienes tus propias páginas de bienvenida o primeros pasos las tienes que editar para cambiar las referencias a naviox.css (como se explica abajo) y quitar todas las referencias a la clase Java NaviOXStyle que ya no existe.

naviox.css renombrado como light.css

Además, se ha movido de Addons a OpenXava. Por tanto, si lo usas en algún JSP personalizado, como welcome.jsp, has de cambiar:

<link href="<%=request.getContextPath()%>/naviox/style/naviox.css?ox=<%=oxVersion%>" 
rel="stylesheet" type="text/css">
Por:
<link href="<%=request.getContextPath()%>/xava/style/light.css?ox=<%=oxVersion%>"
    rel="stylesheet" type="text/css">

Mejor todavía, puedes incluir el CSS del tema actual en lugar de un CSS ad hoc, de esta manera:

<link href="<%=request.getContextPath()%>/xava/style/<%=XavaPreferences.getInstance().getStyleCSS()%>?ox=<%=oxVersion%>"
    rel="stylesheet" type="text/css">

View.findObject() devuelve true si no encuentra el objeto en lugar de lanzar una excepción

Por tanto has de cambiar:
getView().findObject();
Por:
if (!getView().findObject()) {
    addError("object_with_key_not_found")
}
En el código de tus acciones.

Ya no existen los modos desde el punto de vista del usuario (para las pruebas JUnit)

Los modos ya no existen para el usuario. En la lista se puede pulsar una fila o en Nuevo para ir a detalle. En el detalle hay un vínculo "Lista", nada más. Split ya no está disponible. Estos cambios no requieren que modifiques el código de tu aplicación. Los viejos controladores de modo, Mode, DetailOnly, Void, ya no existen pero OpenXava asume Mode en su lugar, por lo que tu código funcionará perfectamente sin ningún cambio. Sin embargo, sí que tendrás que adaptar tus pruebas JUnit a la nueva interfaz de usuario.
El cambio principal es que Mode.detailAndFirst ya no existe, por tanto has de cambiar en tus pruebas:
execute("Mode.detailAndFirst"); -- Cambiar por --> execute("List.viewDetail", "row=0");
Es decir, en lugar de pulsar en la pestaña Detalle, ahora se pulsa en la primera fila. Equivalente en la mayoría de los casos.
Los controladores de modo, Mode, DetailOnly, Void, ya no existen, asumimos Mode en su lugar. Por eso has de cambiar en tu prueba:
execute("DetailList.detailAndFirst"); -- Cambiar por --> execute("List.viewDetail", "row=0"); 
execute("DetailList.list"); -- Cambiar por --> execute("Mode.list");
La acción Mode.split ya no existe, no puedes usarla en tus pruebas:
execute("Mode.split"); // Quita esta línea de tus pruebas, quizás tengas que adaptar tu prueba
Dado que Mode.detailAndFirst y Mode.split ya no existen, si usas assertActions() deberías adaptar la lista de acciones:
private String [] acciones = {
    "Print.generatePdf",
    "Print.generateExcel",
    "ImportData.importData",
    "CRUD.new",
    "CRUD.deleteSelected",
    "CRUD.deleteRow",
    // "Mode.detailAndFirst",     // QUITA ESTA LÍNEA
    // "Mode.split",              // QUITA ESTA LÍNEA
    "List.filter",
    "List.orderBy",
    "List.viewDetail",
    "List.hideRows",
    "List.sumColumn",
    "List.changeConfiguration",
    "List.changeColumnName",
    "ListFormat.select"
}; assertActions(acciones);

Entidad principal se valida antes de abrir el diálogo para crear un nuevo elemento de una colección (for JUnit tests)

Es decir, el código JUnit:
execute("CRUD.new"); 
execute("Collection.new", "viewObject=xava_view_edificios");
Podría falla, porque no rellenamos ningún campo y posiblemente la validación falle, porque ahora se valida la entidad principal al ejecutar Collection.new.
Para resolver este problema tenemos dos opciones. Primero, rellenar los campos requeridos:
execute("CRUD.new");
setValue("nombre", "ALGO"); // AÑADE ESTO
execute("Collection.new", "viewObject=xava_view_edificios");
Funcionaría si nombre es la única propiedad requerida. Si hay muchas propiedades requeridas puede que la segunda opción, buscar una entidad existente, sea mejor:
execute("List.viewDetail", "row=0"); // En lugar de: execute("CRUD.new");
execute("Collection.new", "viewObject=xava_view_edificios");

Para migrar de OpenXava 5.9 a OpenXava 5.9.1

No hay consideraciones.

Para migrar de OpenXava 5.8.1 a OpenXava 5.9

Nuevas acciones en colecciones (para pruebas JUnit)

Las colecciones tienen acciones nuevas disponibles para el usuario (CollectionCopyPaste.cut y CollectionCopyPaste.paste), por tanto si compruebas todas las acciones presentes en tus pruebas junit, necesitarás modificarlas para tener en cuenta la nueva acción CollectionCopyPaste.cut. CollectionCopyPast.paste está oculta por defecto, por lo que podemos ignorarla. Además, List.sumColumn ahora está siempre presente, incluso si la colección está vacía:
String [] acciones = {
    "Navigation.previous",
    "Navigation.first",
    "Navigation.next",
    "CRUD.new",
    "CRUD.save",
    "CRUD.delete",
    "CRUD.refresh",
    "Mode.list",
    "Mode.split",
    "Collection.new",
    "Collection.removeSelected",
    "CollectionCopyPaste.cut", // AÑADE ESTA ENTRADA
    "Print.generatePdf",
    "Print.generateExcel",
    "List.filter",
    "List.orderBy",
    "List.sumColumn", // SIEMPRE PRESENTE, INCLUSO CON LA COLECCIÓN VACÍA
    "List.changeColumnName"
};
assertActions(acciones);

Los booleanos muestran su etiqueta en vez de un icono en las listas

Hasta ahora cuando un booleano era verdadero en la lista, se mostraba un icono de una marca de verificación y si era falso no se mostraba nada. A partir de ahora, si el booleano es verdadero se mostrará su etiqueta, es decir, para una propiedad pagado se mostraría "Pagado". Este cambio no requiere ninguna modificación en el código de tu aplicación, sin embargo es posible que tengas que cambiar alguna prueba JUnit de listas o colecciones. Por ejemplo, si tienes la siguiente línea en tu prueba:
assertValueInList(2, 4, "Yes");
Deberías cambiarla por:
assertValueInList(2, 4, "Pagado");
Si la etiqueta de propiedad es "Pagado".
Y para el caso de falso, deberías cambiar:
assertValueInList(2, 4, "No");
Por:
assertValueInList(2, 4, "");
Por otra parte si quieres mantener el comportamiento clásico, simplemente añade la siguiente entrada a tu fichero editores.xml:
<editor url="booleanEditor.jsp">
  <formateador clase="org.openxava.formatters.BooleanFormatter" >
    <poner propiedad="nullAsFalse" valor="true"/>
  </formateador>
  <formateador-lista clase="org.openxava.formatters.BooleanIconListFormatter" />
  <para-tipo tipo="boolean" />
  <para-tipo tipo="java.lang.Boolean" />
</editor>
Fíjate en el uso de BooleanIconListFormatter como formateador para la lista.

Las páginas de bienvenida y la de inicio de sesión están separadas

Ahora el contenido de welcome.jsp se muestra cuando se va a la raíz de la aplicación. welcome.jsp llena toda la página, por eso deberías modificar tu actual welcome.jsp para incluir <head>, importar los CSSs necesarios e incluir un vínculo a la página de inicio de sesión (m/SignIn). Usa el welcome.jsp incluido por defecto como guía. Usa Addons/web/naviox/welcome.jsp como guía.

Para migrar de OpenXava 5.8 a OpenXava 5.8.1

No hay consideraciones.

Para migrar de OpenXava 5.7.1 a OpenXava 5.8

Nueva acciones en modo lista (para pruebas JUnit)

La lista tiene nuevas acciones disponibles (List.changeColumnName y ImportData.importData), por lo tanto si compruebas todas las acciones presentes en tu prueba junit, tendrás que modificarlo para tener en cuenta las nuevas acciones "List.changeColumnName" e "ImportData.importData":
private String [] accionesLista = {
    "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", // AÑADE ESTA ENTRADA
    "ImportData.importData"  // AÑADE ESTA ENTRADA
};
assertActions(accionesLista);

La acción de borrar no está disponible mientra se está creando un nuevo elemento (para pruebas JUnit)

En v5.8 cuando el usuario pulsa en Nuevo la acción Borrar se oculta. Esto no afecta el código de tu aplicación pero si usas assertActions() en tu pruebas puede que tengas que adaptarlas:
String [] accionesDespuesNuevo = {
 "Navigation.previous",
 "Navigation.first",
 "Navigation.next",
 "CRUD.new",
 "CRUD.save",
 // "CRUD.delete", // QUITA ESTA LÍNEA
 "CRUD.refresh",
 "Mode.list",
 "Mode.split",
 "List.filter",
 "List.orderBy",
 "Print.generatePdf",
 "Print.generateExcel"
};
assertActions(accionesDespuesNuevo);

Acción de buscar ya no está disponible en modo detalle (para pruebas JUnit)

Si usas assertActions() en tus pruebas deberías adaptarlas:
String [] acciones = {
 "Navigation.previous",
 "Navigation.first",
 "Navigation.next",
 "CRUD.new",
 "CRUD.save",
 "CRUD.delete",
 // "CRUD.search", // QUITA ESTA LÍNEA
 "CRUD.refresh",
 "Mode.list",
 "Mode.split",
};
assertActions(acciones);
Si usas CRUD.search en tus pruebas las puedes cambiar por CRUD.refresh, es decir cambia:
execute("CRUD.search");
setValue("numero", "123");
execute("Search.search");
Por:
setValue("numero", "123");
execute("CRUD.refresh");
Además, si quieres que la acción de buscar vuelva puedes usar el nuevo controlador SearchForCRUD que contiene únicamente la acción de buscar. Para definir un módulo con la acción buscar en aplicacion.xml añade el controlador SearchForCRUD:
<modulo nombre="Albaran">
    <modelo nombre="Albaran"/>
    <controlador nombre="Typical"/>
    <controlador nombre="SearchForCRUD"/> <!-- AÑADE ESTA LÍNEA -->
</modulo>
Otra opción es definirlo en controladores.xml de esta manera:
<controlador nombre="Autor">
    <hereda-de controlador="Typical"/>
    <hereda-de controlador="SearchForCRUD"/> <!-- AÑADE ESTA LÍNEA  -->
    <accion nombre="hazAlgo"
        clase="com.miempresa.prueba.acciones.HazAlgo" />
</controlador>
Incluso si vuelves a añadir la acción de buscar con SearchForCRUD has de modificar tus prueba JUnit porque search ya no está en CRUD sino en SearchForCRUD. Por lo tanto has de cambiar:
execute("CRUD.search");
Por:
execute("SearchForCRUD.search");
También tenemos un controlador TypicalWithSearch que tiene todas las acciones de Typical más la acción de buscar, igual que con el Typical de toda la vida. Si quieres que se use por defecto escribe el siguiente código al principio de tu aplicacion.xml:
<modulo-defecto>
    <controlador nombre="TypicalWithSearch"/>
</modulo-defecto>

Módulos sin filas empiezan ejecutando la acción nuevo (para pruebas JUnit)

Deberías tocar las pruebas JUnit con módulos sin filas, porque ahora empiezan en modo detalle. Por ejemplo, deberías cambiar un código como este:
public void testCrearExamenConAlMenosUnaPregunta() throws Exception {
  assertListRowCount(0); // AHORA ESTA LÍNEA FALLA
  execute("CRUD.new");
  setValue("nombre", "ADMISIÓN");
  execute("CRUD.save");
  ...
}
Si el módulo no tiene filas, ahora empieza en modo detalle por tanto la primera línea fallará. Podemos cambiar a modo lista al principio:
public void testCrearExamenConAlMenosUnaPregunta() throws Exception {
  execute("Mode.list"); // AÑADE ESTA LÍNEA
  assertListRowCount(0);
  execute("CRUD.new");
  setValue("nombre", "ADMISIÓN");
  execute("CRUD.save");
  ...
}
O si tu prueba va directamente al modo detalle, como en este ejemplo, simplemente quita la primera parte de la prueba:
public void testCrearExamenConAlMenosUnaPregunta() throws Exception {
  // assertListRowCount(0); // QUITA ESTA LÍNEA
  // execute("CRUD.new"); // QUITA ESTA LÍNEA
  setValue("nombre", "ADMISIÓN");
  execute("CRUD.save");
  ...
}

Para migrar de OpenXava 5.7 a OpenXava 5.7.1

No hay consideraciones.

Para migrar de OpenXava 5.6.1 a OpenXava 5.7

Acción List.changeConfigurationName renombrada como List.changeConfiguration (para pruebas JUnit)

La acción de lista List.changeConfigurationName ahora es List.changeConfiguration, por tanto si compruebas todas las acciones presentes en tus pruebas JUnit, has de modificar el nombre de esta acción:
private String [] accionesLista = {
  "Mode.detailAndFirst",
  "Mode.split",
  "List.filter",
  "List.orderBy",
  "List.viewDetail",
  "List.hideRows",
  "List.sumColumn",
  // "List.changeConfigurationName" // QUITA ESTA ENTRADA
  "List.changeConfiguration" // AÑADE ESTA ENTRADA
};
assertActions(accionesLista);

Propiedades por defecto mejoradas para lista y colecciones (para pruebas JUnit)

Hasta ahora cuando @Tab para la lista, o @ListProperties para las colecciones, se omite por defecto OpenXava muestra todas las propiedades planas de la entidad. A partir de v5.7 cuando @Tab/@ListProperties no está presente las propiedades a mostrar son las planas, los ids de las referencias, el nombre, descripción o título de las referencias o si no está presente la primera propiedad no id de la referencia. Además, las propiedades planas que son oids se excluyen.
Por ejemplo, si tenemos esta clase sin @Tab:
@Entity
public class Factura {
 private int ano;
 private int numero;
 private Date fecha;
 @ManyToOne
 private Cliente cliente;
 
 @Stereotype("ARCHIVOS") @Column(length=32)
 private String archivos;
 
 ...
}
En versiones anteriores hubiéramos obtenido: ano, numero, fecha, archivos
En v5.7 obtenemos: ano, numero, fecha, cliente.numero, cliente.nombre
Si tienes pruebas JUnit contra entidades sin @Tab puede que tengas que adaptarlas.

@NewAction ya no sirve para definir la acción de añadir en las colecciones @OneToMany convencionales

Desde v5.7 las colecciones @OneToMany sin cascade REMOVE tienen disponible a la vez la acción 'Nuevo' para crear nuevos elementos y la acción 'Añadir' para añadir elementos escogiendo entre los ya existentes. Antes de v5.7 solo la acción 'Añadir' estaba disponible y podía definirse con @NewAction. Ahora tenemos una nueva anotación, @AddAction, para la acción 'Añadir' y usamos la vieja @NewAction solo para la acción 'Nuevo'.
Deberías cambiar @NewAction por @AddAction en la colecciones sin cascade REMOVE. Cambia:
@NewAction("Factura.anadirAlbaranes")
@OneToMany(mappedBy="factura")
private Collection<Albaran> albaranes;
Por:
@AddAction("Factura.anadirAlbaranes")
@OneToMany(mappedBy="factura")
private Collection<Albaran> albaranes;

Colecciones de entidades sin REMOVE cascade permiten editar los elementos (para pruebas JUnit)

No necesitas cambiar tu código de aplicación, simplemente adaptar tus pruebas JUnit cambiando:
execute("Collection.view", "row=1,viewObject=xava_view_customers");
Por:
execute("Collection.edit", "row=1,viewObject=xava_view_customers");
Fíjate que ahora no es "Collection.view" sino "Collection.edit".

Optimizadas las etiquetas automáticas para las referencias en la lista (para pruebas JUnit)

Cuando en un lista tenemos un propiedad de una referencia y la propiedad se llama "nombre", "descripcion" o "titulo", el nombre de la propiedad se omite, simplemente se usa el nombre de la referencia. Es decir, en lugar de "Nombre de Cliente" ahora es solamente "Cliente". Esto no afecta al código de tu aplicación en absoluto, pero si verificas las etiquetas de alguna lista en tus pruebas JUnit, deberás de adaptarlo.
Cambia esto:
assertLabelInList(4, "Nombre de Cliente");
Por esto:
assertLabelInList(4, "Cliente");

Para migrar de OpenXava 5.6 a OpenXava 5.6.1

No hay consideraciones.

Para migrar de OpenXava 5.5.1 a OpenXava 5.6

La acción ExtendedPrint.myReports ya no está disponible por defecto (para pruebas JUnit)

Por lo tanto compruebas todas las acciones presentes en tu prueba JUnit, tendrás que modificarlo eliminando ExtendedPrint.myReports de la lista:
private String [] accionesLista = {
    "Print.generatePdf",
    "Print.generateExcel",
    // ELIMINA ESTA LÍNEA "ExtendedPrint.myReports",
    "CRUD.new",
    "CRUD.deleteSelected",
    ...
};
assertActions(accionesLista);
Aunque la acción no esté disponible por defecto, todavía existe en OpenXava y funciona perfectamente. De hecho, hay un nuevo controlador TypicalExtendedPrint para facilitar su uso. Si quieres continuar usando la funcionalidad Mis informes cambia Typical por TypicalExtendedPrint en tu aplicacion.xml y controladores.xml, incluso lo puedes declarar como controlador por defecto.

Nueva acción en lista (para pruebas junit)

La lista tiene una nueva acción disponible (List.changeConfigurationName), por lo tanto si compruebas todas las acciones presentes en tu prueba junit, tendrás que modificarlo para tener en cuenta la nueva acción "List.changeConfigurationName":
private String [] accionesLista = {
  "Mode.detailAndFirst",
  "Mode.split",
  "List.filter",
  "List.orderBy",
  "List.viewDetail",
  "List.hideRows",
  "List.sumColumn",
  "List.changeConfigurationName" // AÑADE ESTA ENTRADA
};
assertActions(accionesLista);

Para migrar de OpenXava 5.5 a OpenXava 5.5.1

Necesario llamar a super dentro de setUp() de las pruebas antes de usar JPA

A partir de v5.5.1 la inicialización de JPA en las pruebas ModuleTestBase se hace en el método setUp(), por lo que si usas JPA dentro de un método setUp() has de llamar a super antes. Es decir, si tienes un código como este en tu prueba:
protected void setUp() throws Exception {
    crearEntidadesUsandoJPA(); // Ahora falla, porque JPA todavía no está inicializado
    super.setUp();
}
Cámbialo por:
protected void setUp() throws Exception {
    super.setUp(); // JPA se incializa aquí
    crearEntidadesUsandoJPA();
}

Para migrar de OpenXava 5.4.1 a OpenXava 5.5

Los combos para @DescriptionsList ya no son selects de HTML (sólo si usas el API de HtmlUnit)

Los combos para @DescriptionsList ahora se crean usando un input text de HTML más algo de código JavaScript y CSS para simular un combo. Esto no requiere ningún cambio en el código de tu aplicación, ni siquiera has de cambiar el código de tus pruebas jUnit si sólo usas los métodos de ModuleTestBase. Sin embargo, si usas el API de HtmlUnit directamente, por ejemplo con getHtmlPage() o getWebClient() en tus pruebas, y manejas un combo de un @DescriptionList. En ese caso tienes que adaptar tu código, cambiando:
form.getSelectByName("ox_MiAp_MiModulo__miReferencia___id").setSelectedAttribute("ElValor", true);
Por:
HtmlInput comboInput = form.getInputByName("ox_MiAp_MiModulo__miReferencia___id");
comboInput.setValueAttribute("ElValor");
((HtmlInput) comboInput.getPreviousElementSibling()).setValueAttribute("Algo"); // Un truco para evitar que JavaScript borre el valor real
((HtmlInput) comboInput.getNextElementSibling()).setValueAttribute("Algo"); // Un truco para evitar que JavaScript borre el valor real

Para migrar de OpenXava 5.4 a OpenXava 5.4.1

No hay consideraciones.

Para migrar de OpenXava 5.3.2 a OpenXava 5.4

Iconos en lugar de imágenes para las acciones

A partir de v5.4 las acciones estándar de OpenXava usan iconos de Material Design Icons en vez de imágenes gif o png. El atributo imagen de <accion/> en controllers.xml continúa funcionando como siempre, sin embargo tenemos un nuevo atributo icono que es el que se usa en las acciones estándar. El efecto es que en tu aplicación todas las acciones estándar usaran los nuevos iconos monocromo y tus acciones propias usarán las vieja acciones en color con imágenes gif y png. Esto podría quedar un poco feo, para arreglarlo cambia imagen por icono en tus acciones. Por ejemplo, cambia:
<accion nombre="borrar" modo="detalle" confirmar="true"
    clase="com.miempresa.miaplicacion.acciones.MiBorrar"
    imagen="delete.gif"
    atajo-de-teclado="Control D"/>
Por esto:
<accion nombre="borrar" mode="detalle" confirmar="true"
    clase="com.miempresa.miaplicacion.acciones.MiBorrar"
    icono="delete"
    atajo-de-teclado="Control D"/>
Para ver todos los iconos disponibles visita Material Design Icons.
Por otra parte, si prefieres seguir con los viejos iconos de toda la vida, simplemente añade la siguiente línea en xava.properties:
useIconsInsteadOfImages=false
De esta manera todas las acciones, incluyendo las estándar, usarán las viejas imágenes en color.

Para migrar de OpenXava 5.3.1 a OpenXava 5.3.2

No hay consideraciones.

Para migrar de OpenXava 5.3 a OpenXava 5.3.1

El jar de HSQLDB se ha movido desde OpenXavaTest a OpenXava

Si referencias a este jar tendrás que cambiar la ruta. Por ejemplo, si utilizas HSQLDB en alguno de tus proyectos, deberías cambiar en la tarea Ant actualizarEsquema de build.xml esto:
<property name="schema.path" value="../OpenXavaTest/lib/hsqldb.jar"/>
Por esto:
<property name="schema.path" value="../OpenXava/lib/hsqldb.jar"/>

Para migrar de OpenXava 5.2.1 a OpenXava 5.3

Hibernate actualizado a 4.3

Si usas la API de JPA o haces un uso básico de la API de Hibernate no tendrás que cambiar nada. Ahora bien, si usas características avanzadas de Hibernate seguramente esta actualización te afecte.
Por ejemplo, si tienes tu propios tipos de Hibernate (UserType) has de cambiar en tu definición de tipo lo siguiente:
public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
Por:
public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor sessionImplementor, Object owner) throws HibernateException, SQLException {
Y esto:
public void nullSafeSet(PreparedStatement ps, Object value, int index) throws HibernateException, SQLException {
Por:
public void nullSafeSet(PreparedStatement ps, Object value, int index, SessionImplementor sessionImplementor) throws HibernateException, SQLException {
Por supuesto, si llamas a estos métodos debes de adaptar la llamada. Por ejemplo, un código como este:
((UserType) hibernateType).nullSafeSet(ps, o, 1);
Se quedaría:
((UserType) hibernateType).nullSafeSet(ps, o, 1, null);
Fíjate en que enviar un nulo para el nuevo parámetro es suficiente.
Además, en lugar de Hibernate.INTEGER has de usar IntegerType.INSTANCE.
La forma de registrar los eventos ha cambiado, esto te afecta sólo si usas componentes XML con el API de JPA, en cuyo caso has de quitar el registro de eventos de tu persistence.xml, como sigue:
<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"/>
        <!-- ELIMINA LAS SIGUIENTES LÍNEAS
        <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>
También si usas componentes XML ya no puedes tener una referencia usada como clave si el valor no existe en la tabla referenciada. Este caso ya no está permitido por Hibernate. Este caso nunca ha estado permitido en JPA. Deberías de pensar en una forma diferente de resolver el problema, como añadiendo una clave autogenerada o creando el registro en la tabla referenciada.
Con Hibernate 4.3 la forma por defecto de liberar una conexión ha cambiado, por lo que te podrías encontrar un "Could not open connection error". Para evitarlo añade la siguiente línea a tu persistence.xml:
<persistence-unit name="default">
    ...
    <properties>
        ...
        <!-- Añade la siguiente línea -->
        <property name="hibernate.connection.release_mode" value="after_transaction"/>
 
    </properties>
 
</persistence-unit>

Hibernate Validator 3 quitado de la distribución

Hasta ahora hemos incluido ambos, el antiguo Hibernate Validator 3 y la última versión de Hibernate Validator, en OpenXava para conseguir la máxima compatibilidad del código antiguo. Por desgracia, Hibernate 4.3 no soporta Hibernate Validator 3, por eso hemos tenido que quitarlo de OpenXava.
Si simplemente usas anotaciones de validación como @Max, @Length, @Size, etc. es suficiente con cambiar los imports, cambia:
import org.hibernate.validator.*;
Por:
import javax.validation.constraints.*;
import org.hibernate.validator.constraints.*;
En el caso de @Digits aparte de cambiar los susodichos imports tienes que cambiar los nombres de los parámetros, cambiando esto:
@Digits(integerDigits=10, fractionalDigits=6)
Por esto:
@Digits(integer=10, fraction=6)
Ya no puedes usar InvalidStateException de Hibernate Validator 3. Por lo tanto, si la usas para lanzar un error de validación desde tu entidad u acción tendrás que cambiarla por otra excepción. Por ejemplo, un código como el siguiente:
@PreRemove
public void validarAlBorrar() {
    if (numero == 1) {
        throw new InvalidStateException(
            new InvalidValue [] {
                new InvalidValue(
                    "uno_no_se_puede_borrar", getClass(), "numero",
                    getNumero(), this)
            }
        );
    }
}
Ahora podría escribirse de esta manera:
@PreRemove
public void validarAlBorrar() {
    if (numero == 1) {
        throw new javax.validation.ValidationException("uno_no_se_puede_borrar");
    }
}
Si has definido tu propio validador con el Hibernate Validator antiguo deberías reescribirlo usando el estándar Bean Validation. No te preocupes, la conversión es muy sencilla. En tu anotación cambia @ValidatorClass por @Constraint y añade groups() y payload(), así:
@Constraint(validatedBy = MyValidator.class) // En lugar de @ValidatorClass(PropertyValidatorValidator.class)
public @interface MyAnnotation {
 
    ...
 
    // Añade el siguiente código
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
 
}
Y en tu clase validador, cambia esto:
public class RequiredValidator implements Validator<Required> {
Por:
public class RequiredValidator implements ConstraintValidator<Required, Object> {
Y esto:
public boolean isValid(Object value) {
Por:
public boolean isValid(Object value, ConstraintValidatorContext context) {
Puedes dejar el resto del código como está.

@Required, @PropertyValidator y @EntityValidator son restricciones de Bean Validation

Antes eran restricciones de Hibernate Validator 3. Si haces tu propio commit y tratas de capturar la excepción de validación has de cambiar la excepción a atrapar. Si tienes un código como este:
try {
    XPersistence.commit();
}
catch (RollbackException ex) {
    if (ex.getCause() instanceof InvalidStateException) {
        InvalidStateException iex = (InvalidStateException) ex.getCause();
        int cantidadValoresInvalidos = iex.getInvalidValues().length;
        String propiedad = iex.getInvalidValues()[0].getPropertyName();
        String mensaje = iex.getInvalidValues()[0].getMessage();
        ...
    }
}
Deberías escribirlo de esta manera:
try {
    XPersistence.commit();
}
catch (RollbackException ex) {
    if (ex.getCause() instanceof ConstraintViolationException) {
        ConstraintViolationException cex = (ConstraintViolationException) ex.getCause();
        int cantidadValoresValidos = cex.getConstraintViolations().size();
        ConstraintViolation v = cex.getConstraintViolations().iterator().next();
        String propiedad = v.getPropertyPath().toString());
        String mensaje = v.getMessage());
        ...
    }
}

Prefijo para JNDI en Tomcats antiguos

Hibernate 4.3 usa una forma diferente de buscar los recursos JNDI que funciona bien con Tomcat 7.0.27 (y superior) y Tomcat 6.0.36 (y superior) pero falla con versiones anteriores. Esto no es un bug de Hibernate sino un bug del Tomcat. Por suerte, hay un truco para hacer que el nuevo Hibernate funcione incluso con las versiones antiguas de Tomcat, simplemente añade un // al nombre JNDI. Es decir, si estás usando una versión de Tomcat anterior a 7.0.27 o 6.0.36 cambia en tu persistence.xml esto:
<non-jta-data-source>java:comp/env/jdbc/TuAplicacionDS</non-jta-data-source>
Por esto:
<non-jta-data-source>java://comp/env/jdbc/TuAplicacionDS</non-jta-data-source>
Y en hibernate.cfg.xml cambia esto:
<property name="hibernate.connection.datasource">java:comp/env/jdbc/TuAplicacionDS</property>
Por esto otro:
<property name="hibernate.connection.datasource">java://comp/env/jdbc/TuAplicacionDS</property>
Fíjate en // antes de comp. Si usas nombres JNDI en otras partes de tu aplicación también tendrías que cambiarlos. Lo bueno es que las nuevas versiones de Tomcat también funcionan de esta forma, por tanto si usas siempre esta notación tu aplicación funcionará en cualquier Tomcat.

Actualización de librerias EL para Tomcat 6

Si usas Tomcat 6 copia el-api.jar y jasper-el.jar de la carpeta lib del Tomcat incluido en OpenXava (o cualquier Tomcat 7) a la carpeta lib de tu Tomcat 6. Esto es requerido por última versión de Hibernate Validator.

Librería Automated Business Logic (ABL) quitada de la distribución

Por desgracia, ABL no soporta Hibernate 4.3. Además, ABL ha sido descontinuada desde 2012, por tanto tampoco soportará Hibernate 4.3 en el futuro. Por lo tanto, no tenemos otra opción que quitar ABL de la distribución de OpenXava. Por suerte, mover la lógica en las anotaciones ABL a código Java es fácil. Por ejemplo, si tienes una clase de lógica ABL como esta:
public class PedidoLogic {
 
    @Formula("precioProducto * cantidad")
    public void deriveImporte() { }
 
}
Borra la clase de arriba y mueve el cálculo en la anotación @Formula a un método @PrePersist y @PreUpdate en la entidad. Así:
@Entity
public class Pedido {
 
    ...
 
    @PrePersist @PreUpdate
    private void deriveImporte() {
        importe = new BigDecimal(cantidad).multiply(precioProducto);
    }
}
Además, has de eliminar la siguiente entrada de tu persistence.xml:
<property name="hibernate.current_session_context_class"
    value="com.autobizlogic.abl.session.LogicThreadLocalSessionContext"/>

schema.path necesario en tarea ant generarEsquema

Esto afecta a generarEsquema no a actualizarEsquema. Si tienes una tarea generarEsquema en tu build.xml, añade schema.path, como sigue:
<!-- Genera el esquema desde cero. Lo muestra en consola, pero no lo ejecuta -->
<target name="generarSchema">
 
    <ant antfile="../OpenXava/build.xml" target="generateSchemaJPA">
        <property name="persistence.unit" value="junit"/>
        <!-- AÑADE LA SIGUIENTE LÍNEA PARA v5.3 -->
        <property name="schema.path" value="../OpenXavaTest/lib/hsqldb.jar"/>
    </ant>
 
</target>

Para migrar de OpenXava 5.2 a OpenXava 5.2.1

Entidad obtenida de la vista tiene nulos para referencias inexistentes

Hasta v5.2 todas las referencias de una entidad obtenida vía getView().getEntity() tenían valor, incluso si las referencias no existían. Esto producía un error muy feo porque JPA trataba de grabar los objetos transitorios como referencias. A partir de v5.2.1, las referencias vacías son nulo, esto es más natural (funciona como cuando obtenemos los objetos de la base de datos) y resuelve el susodicho error.
Si tienes código que confía en este comportamiento tienes que cambiarlo. Es decir, has de hacer cambios como este:
Factura factura = (Factura) getView().getEntity();
if (factura.getCliente().getCodigo() == 0) { // En v5.2 si cliente está vacío se devuelve un cliente vacío
Por:
Factura factura = (Factura) getView().getEntity();
if (factura.getCliente() == null) { // En v5.2.1 si cliente está vacío se devuelve nulo

Para migrar de OpenXava 5.1.x a OpenXava 5.2

HtmlUnit actualizado a 2.15

Si usas HtmlUnit directamente en tus pruebas jUnit por medio de getHtmlPage() o getWebClient() deberías adaptar tu código a la nueva API de HtmlUnit. Por ejemplo, deberías cambiar:
getWebClient().setCssEnabled(true);
Por:
getWebClient().getOptions().setCssEnabled(true);
Y:
HtmlElement consola = getHtmlPage().getElementById("xava_console");
Por:
HtmlElement consola = getHtmlPage().getHtmlElementById("xava_console");
Y muchas más cosas. Por desgracia, el equipo de HtmlUnit refactoriza su librería en cada nueva versión menor, por tanto HtmlUnit nunca es compatible hacia atrás.

Para migrar de OpenXava 5.0.x a OpenXava 5.1

@DefaultValueCalculator dependiente de otras propiedades cambia su comportamiento

Si tienes un calculador por defecto como este:
@DefaultValueCalculator(
    value=CalculadorPrecioUnitario.class,
    properties=@PropertyValue(
        name="numeroProducto",
        from="producto.numero")
)
private BigDecimal precioUnitario;
Con versiones anteriores a 5.1 cuando producto.numero cambia precioUnitario se recalcula solo si no tiene valor todavía. Desde la versión 5.1 precioUnitario se recalcula siempre que producto.numero cambia.
Este nuevo comportamiento es más natural, por tanto si no cambias nada tus usuarios tendrán una aplicación que funciona mejor. De todas formas, puede ser que quieras que el valor se recalcule sólo la primera vez, como antes. En ese caso deberías reescribir tu lógica usando @OnChage, es decir, deberías cambiar el código de arriba por este:
@OnChange(RecalcularPreciOUnitarioAlCambiarProducto.class)
private Producto producto;
 
private BigDecimal precioUnitario;

Para migrar de OpenXava 4.9.1 a OpenXava 5.0

La identifación de usuarios afecta a tus pruebas jUnit

Ahora es obligatorio que el usuario se identifique antes de ejecutar un módulo, por tanto tus actuales pruebas jUnit fallarán. Para resolver esto desactiva el mecanismo de identificación de usuarios añadiendo las siguientes entradas al archivo naviox.properties en properties folder:
autologinUser=admin
autologinPassword=admin
De esta manera tus pruebas funcionarán bien sin necesidad de recodificarlas.
Otra opción es dejar el mecanismo de identificación activo y añadir la lógica de identificación en tu código de pruebas:
public void testMiPrueba() throws Exception {
    login("admin", "admin");
    ...
}

Ejecutar los módulos en solitario ya no está disponible por defecto

Cuando vas a /MiAplicacion/modules/MiModule con tu navegador, el modulo se muestra con menus e identificación de usuarios incluidos. Esto no es un problema en absoluto, porque los menús son muy ligeros y la identificación de usuario puede desactivarse con autologinUser y autologinPassword en naviox.properties. Además, dentro de Liferay los módulos funcionan como siempre.
Pero si por alguna razón prefieres trabajar de la forma antigua puedes desactivar la identificación de usuarios y los menús y usar el viejo estilo visual para tus módulos en OpenXava 5. Para hacerlo edita el archivo web.xml del proyecto OpenXava y quita:
<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>
Además cambia:
<servlet>
    <servlet-name>naviox</servlet-name>
    <servlet-class>com.openxava.naviox.web.NaviOXServlet</servlet-class>
</servlet>
Por:
<servlet>
    <servlet-name>modules</servlet-name>
    <servlet-class>org.openxava.web.servlets.ModuleServlet</servlet-class>
</servlet>
Y cambia:
<servlet-mapping>
    <servlet-name>naviox</servlet-name>
    <url-pattern>/modules/*</url-pattern>
</servlet-mapping>
Por:
<servlet-mapping>
    <servlet-name>modules</servlet-name>
    <url-pattern>/modules/*</url-pattern>
</servlet-mapping>
Finalmente quita:
<servlet-mapping>
    <servlet-name>naviox</servlet-name>
    <url-pattern>/m/*</url-pattern>
</servlet-mapping>
Con estos cambios en OpenXava/web.xml has eliminado los menús y la identificación de usuarios. Tienes que ejecutar la tarea ant actualizarOX para actualizar el web.xml en tu proyecto.
Para usar el estilo visual de OpenXava 4 añade las siguientes entradas a xava.properties de tu proyecto:
styleClass=org.openxava.web.style.Liferay51Style
styleCSS=liferay51/css/everything_unpacked.css

El estilo nativo de iPad no se usa por defecto

Cuando accedes a una aplicación OpenXava 5 desde un iPad el estilo es el mismo que en un navegador de escritorio, el estilo iPad no se muestra por defecto. Esto es así porque el estilo iPad sólo funciona en módulos en solitario, que OpenXava 5 no usa por defecto. Si quieres usar el estilo nativo de iPad sigue las instrucciones de arriba en la sección Ejecutar los módulos en solitario ya no está disponible por defecto para activar lo módulos en solitario.
Sobre el soporte de iPad y tabletas vamos a tener un único estilo que funcione bien para escritorio y tabletas, un estilo adaptable (responsive).

Las clases transitorias requieren un declaración expicita de módulo

Por ejemplo, si tienes una clase transitoria llamada FiltroPorMes con un controlador llamado FiltroPorMes y pruebas la URL /MiAplicacion/modules/FiltroPorMes, no funcionará hasta que declares el módulo en aplicacion.xml como sigue:
<modulo nombre="FiltroPorMes">
    <modelo nombre="FiltroPorMes"/>
    <controlador nombre="FiltroPorMes"/>
</modulo>
De todas formas, siempre ha sido necesario declarar los módulos para las clases transitorias si queriamos generar portlets, por lo tanto si trabajas con portales ya tendrás los módulos definidos.

Nivel de log FINEST genera un montón de traza

Hasta ahora el nivel de log FINEST producía poca traza, pero a partir de v5.0 OpenXava genera abundante traza con FINEST. Por tanto has de editar tu archivo xava.properties y cambiar:
javaLoggingLevel=FINEST
Por:
javaLoggingLevel=FINE
Si quieres mantener una cantidad de traza moderada.
Hasta v4.9.1 los proyectos OpenXava creados con OpenXavaPlantilla tenían FINEST configurado por defecto, a partir de v5.0 tienen FINE.

Eliminada clase Objects de org.openxava.util

Esta clase entra en conflicto con la clase java.util.Objects de Java 7. En lugar de calificar la clase en todos sitios preferimos renombrarla a XObjects. En tu código has de reemplazar Objects por XObjects, como sigue:
Objects.execute(miObjeto, "hacerAlgo");
Ahora tienes que escribir en su lugar:
XObjects.execute(miObjeto, "hacerAlgo");

AccessTracking quitado de la distribución

Puedes continuar usando AccessTracking sin ningún problema, simplemente ejecuta la tarea ant updateOX de AccessTracking después de ejecutar OpenXava.

La URL usada por ModuleTestBase incluye un parámetro por defecto

Esto sólo te afecta si sobrescribes getModuleURL() para añadir parámetros. En este caso simplemente cambia ? por &:
public class MiModuloTest extends ModuleTestBase {
 
    ...
 
    @Override
    protected String getModuleURL() {
        // return super.getModuleURL() + "?miParametro=5"; // Con ? en v4.x.x
        return super.getModuleURL() + "&miParametro=5"; // Con & en v5.0
    }
}

@Digits anula la escala por defecto

Cuando @Digits se especifica la escala por defecto se ignora, incluso si la fracción no se especifica. Es decir, si escribes:
@Digits(integer=10)
private BigDecimal importe;
Con v4.x tiene 2 cifras decimales porque la escala por defecto para BigDecimal es 2. Sin embargo, a partir de v5.0 tiene 0 cifras decimales, porque no especificar fracción es lo mismo que poner fraction=0. Esto te permite tener números BigDecimal con 0 para la parte decimal, pero podría hacer que algunas de tus actuales propiedes numéricas dejen de usar 2 dígitos para la fracción. Para arreglarlo simplemente especifíca la fracción explicitamente, así:
@Digits(integer=10, fraction=2)
private BigDecimal importe;

Formateo de BigDecimal arreglado (para pruebas jUnit)

La escala definida en default-size.xml, en @Column y @Digits se ignoraba al formatear. Lo hemos arreglado. Sí, el formateo de los número funciona mejor, pero tienes que adaptar tus pruebas. Por ejemplo, si usas BigDecimal sin anotaciones deberías cambiar:
assertValue("miNumeroBigDecimal", "20");
por esto:
assertValue("miNumeroBigDecimal", "20.00");

Para migrar de OpenXava 4.9 a OpenXava 4.9.1

Modificador de acceso del método getFrame() cambiado

El modificador de acceso del método getFrame() de org.openxava.web.style.Style fue cambiado de protected a public. Las clases que sobrescriben el método getFrame() requieren que se les cambien el modificador de acceso de protected a public.

Para migrar de OpenXava 4.8.1 a OpenXava 4.9

Cabeceras de informes PDF pueden ocupar varias líneas

Esto no afecta al codigo de tu aplicación en absoluto. Sin embargo, si verificas el contenido del PDF en tus pruebas automáticas quizás necesites hacer algunos ajustes. Por ejemplo, el siguiente código fallaría si la cabecera del informe ahora usará 2 líneas en vez de 1.:
assertPopupPDFLinesCount(5); // Quizás ahora hay 6 líneas, porque la cabecera usa 2 líneas

Controlador CustomReport renombrado a MyReport

Es poco probable que tengas que cambiar tu código, porque este controlador es para uso interno del diálogo 'Mis informes' y sólo está disponible desde OpenXava 4.6. Sin embargo, si has usado acciones del controlador CustomReport en tus pruebas jUnit has de renombrarlas a MyReport.

Para migrar de OpenXava 4.8 a OpenXava 4.8.1

Ocultar un miembro cuyo nombre es el mismo que la sección que lo contiene

Hemos arreglado View.setHidden() para que funcione con secciones también, ya funcionaba con grupos pero no con secciones. Por lo tanto, si tienes una vista como esta:
@View(members=
  ...
  "observaciones { consejo, atajo; observaciones }"
  ...
)
Donde la propiedad observaciones está dentro de una sección llamada observaciones. Hasta ahora si escribías esto:
getView().setHidden("observaciones", true);
Ocultabas la propiedad observaciones, sin embargo desde OpenXava 4.8.1 ocultarás la sección observaciones. En este caso, si aún quieres ocultar la propiedad en lugar de la sección deberías renombrar la sección, como sigue:
@View(members=
   ...
   "comentarios { consejo, atajo; observaciones }"
   ...
)

Para migrar de OpenXava 4.7.1 a OpenXava 4.8

Sin consideraciones.

Para migrar de OpenXava 4.7 a OpenXava 4.7.1

La acción Gallery.return ha sido renombrada como Gallery.close

Esto es porque ahora el editor Gallery usa un diálogo en vez de una vista plana. Además, el controlador para Gallery de solo lectura es Close en vez de Return. Es poco probable que tengas que tocar tu código por estos cambios. Sin embargo, si la has usado en pruebas jUnit tendrás que renombrarla.

Para migrar de OpenXava 4.6.1 a OpenXava 4.7

La acción ExtendedPrint.customReport ha sido renombrada como ExtendedPrint.myReports

Es poco probable que tengas que tocar tu código por este cambio, porque esta es una acción de Typical (por tanto siempre presente) y disponible sólo desde OpenXava 4.6. Sin embargo, si la has usado en pruebas jUnit, @Action o IChainAction, tendrás que renombrarla.

El método getSelected() de Tab y TabBaseAction obsoleto, ahora usamos getSelectedKeys()

El método getSelected() incluido en Tab y TabBaseAction ha sido marcado como obsoleto (deprecated) en sustitución tenemos disponible el método getSelectedKeys() que nos devuelve las claves (Map) de los elementos que se hayan seleccionado.
En la mayoría de casos getSelected() devolverá correctamente las filas que se han seleccionado, pero en el caso de tener alguna fila seleccionada fuera del rango de páginas cargadas no lo hará. Esto ocurrirá por ejemplo si seleccionamos una fila y después ordenamos por algún campo y esta fila queda fuera del rango de páginas cargadas, getSelected() no devolverá esta fila getSelectedKeys() sí.
En nuestro código cambiaremos:
int[] selected = tab.getSelected();
for (int i = 0; i < selected.length; i++){
     Map clave = (Map) tab.getTableModel().getObjectAt(selected[i]);
     ....
}
por
Map[] selected = tab.getSelectedKeys();
for (int i = 0; i < selected.length; i++){
     Map clave = selected[i];
     ....
}

Suprimido método deselectVisualizedRows de la clase Tab


Para migrar de OpenXava 4.6 a OpenXava 4.6.1

Mensajes en archivos i18n sin argumentos ahora son formateados de manera estándar

Esto es realmente el arreglo de un fallo, pero puede afectar tus mensajes i18n si estos contienen apóstrofes, por tanto has de cambiar:
mi_mensaje=T'ha dit que no
por
mi_mensaje=T''ha dit que no
Fíjate como hay que cambiar ' por ''.

Para migrar de OpenXava 4.5.1 a OpenXava 4.6

Sin consideraciones.

Para migrar de OpenXava 4.5 a OpenXava 4.5.1

Los editores personalizados han de especificar el atributo tabindex

Para estar en el orden correcto de tabulación los editores tienen que especificar tabindex="1" en su HTML, así:
<input id="<%=propertyKey%>"
    name="<%=propertyKey%>" class="<%=style.getEditor()%> <%=numericClass%>"
    type="<%=inputType%>"
    tabindex="1" <!-- Ahora hay que poner esto -->
    ...
/>

Para migrar de OpenXava 4.4.x a OpenXava 4.5

Select íntegro en baseCondition de @Tab ahora tiene que usar sintaxis JPQL y no SQL

A partir de v4.5 OpenXava usa JPA para obtener datos tabulares, antes usaba SQL. Esto significa que cuando uses baseCondition para escribir un select completo has de utilizar la sintaxis JPQL, SQL ya no se soporta.
Es decir, si tienes un select como este:
baseCondition =
    "select CODIGO, DESCRIPCION, FAMILIA.DESCRIPCION " +
    "from   XAVATEST.SUBFAMILIA, XAVATEST.FAMILIA " +
    "where  SUBFAMILIA.FAMILIA = FAMILIA.CODIGO"
Lo has de reescribir de esta forma:
baseCondition =
    "select e.codigo, e.descripcion, f.descripcion " +
    "from Subfamilia e, Familia f " +
    "where e.codigoFamilia = f.codigo"
La sintaxis de JPQL y SQL son muy parecidas, normalmente no es necesario hacer grandes cambios más allá de cambiar los nombres de tablas y columnas por nombres de propiedades y tablas. Has de usar e como alias para la entidad principal.

El atributo condition de @DescriptionsList ahora usa sintaxis JPQL y no SQL

A partir de v4.5 OpenXava usa JPA para obtener datos de los combos, por tanto has de usar sintaxis JPQL en condition. Si no usas condiciones demasiado complicadas y usas ${nombrePropiedad} en vez de nombre de columna, seguramente no tendrás que hacer ningún cambio. Sin embargo, puede ser que necesitas hacer algún cambio, especialmente si usas nombres de columna. Por ejemplo, el siguiente código ya no funciona:
@DescriptionsList(
    // No funciona porque IDCOSA es un nombre de columna, por eso JPA no lo reconoce
    condition="${cosa.codigo} = (SELECT IDCOSA FROM ${Cosa} WHERE nombre = 'COCHE')"
)
La solución es usar nombres de propiedades en vez de nombres de columnas, en este caso cambiando IDCOSA por codigo es suficiente para resolver el problema:
@DescriptionsList(
    // Funciona porque usamos el nombre de propiedad, codigo, en vez de IDCOSA
    condition="${cosa.codigo} = (SELECT codigo FROM ${Cosa} WHERE nombre = 'COCHE')"
)
Otra opción es escribir la sentencia completa en puro JPQL, dado que los ${} ya no son necesarios, como sigue:
@DescriptionsList(
    // Podemos usar JPQL puro sin ${nombrePropiedad}
    condition="e.cosa.codigo = (SELECT c.codigo FROM Cosa c WHERE c.nombre = 'COCHE')"
)
Si usas JPQL has de usar e como alias para la entidad principal.

@OnSelectElementAction no refresca por defecto su colección

Este nuevo comportamiento produce un rendimiento mucho mayor en la mayoría de los casos, especialmente cuando trabajas con una colección muy grande y seleccionas elementos que no cambian los datos de la colección. Sin embargo, si tienes un caso donde tu @OnSelectElementAction cambia el contenido de la colección has de refrescar las colecciones explicitamente, como sigue:
public class MiOnSelectElementAction extends OnSelectElementBaseAction {
 
    public void execute() throws Exception {
        hacerAlgoQueModificaLaColeccion();
        getView().refreshCollections(); // A partir de v4.5 has de añadir esta linea
    }
 
}

Para migrar de OpenXava 4.3.x a OpenXava 4.4

HtmlUnit actualizado de 2.5 a 2.9

HtmlUnit es la librería que se usa para simular un navegador desde las pruebas jUnit. Se ha actualizado a la versión 2.9. HtmlUnit ha renombrado y eliminado algunos métodos y clases, de hecho la gente de HtmlUnit está siempre refactorizando su librería (refactorizar es bueno para las aplicaciones pero no lo es tanto para una libreria). Lo más probable es que no tengas que cambiar nada en tus pruebas jUnit porque ModuleTestBase oculta HtmlUnit, sin embargo si usas la API de HtmlUnit directamente, usando getHtmlPage() de ModuleTestBase por ejemplo, quizás tengas que adaptar algunas llamadas a métodos.

Para migrar de OpenXava 4.2.x a OpenXava 4.3

Sin consideraciones.

Para migrar de OpenXava 4.1.x a OpenXava 4.2

Sin consideraciones.

Para migrar de OpenXava 4.0.1 a OpenXava 4.1

Nueva acción en lista y colecciones (para pruebas junit)

La lista y las colecciones tienen una nueva acción disponible (List.sumColumn), por lo tanto si compruebas todas las acciones presentes en tu prueba junit, tendrás que modificarlo para tener en cuenta la nueva acción "List.sumColumn":
private String [] accionesLista = {
  "Mode.detailAndFirst",
  "Mode.split",
  "List.filter",
  "List.customize",
  "List.orderBy",
  "List.viewDetail",
  "List.hideRows",
  "List.sumColumn" // AÑADE ESTA ENTRADA
};
assertActions(accionesLista);

Para migrar de OpenXava 4.0 a OpenXava 4.0.1

Ya no hay conversor por defecto para boolean

A partir de ahora no hay conversor por defecto denido en default-converters.xml para java.lang.Boolean y boolean. En realidad, esto no produce ningún problema de incompatibilidad en las aplicaciones JPA, ya que en estas aplicaciones el motor JPA hace la coversión el mismo. Sin embargo, si tienes una aplicación XML antigua, sólo has de regenerar el código y todo funcionará perfectamente, porque la mayoría de las bases de datos hace un buen trabajo al traducir de boolean a numérico automáticamente. De todas formas, puedes configurar tu aplicación para que funcione como antes, simplemente añade las siguiente líneas al archivo conversores.xml en la carpeta xava de tu aplicación:
<para-tipo tipo="boolean"
  clase-conversor="org.openxava.converters.Boolean01Converter"
  tipo-cmp="java.lang.Integer"/>
 
<para-tipo tipo="java.lang.Boolean"
  clase-conversor="org.openxava.converters.Boolean01Converter"
  tipo-cmp="java.lang.Integer"/>
Recuerda, añadir estás líneas no suele ser necesario, regenerar código sin más debería ser suficiente. Y si tu aplicación es JPA (el caso más normal) no necesitas hacer nada.

Para migrar de OpenXava 4m6 a OpenXava 4.0

Sin consideraciones.

Para migrar de OpenXava 4m5 a OpenXava 4m6

Hibernate actualizado a Hibernate 3.6

En OpenXava 4m6 Hibernate ha sido actualizado a Hibernate 3.6 para poder soportar JPA 2.0. La mayoría del código funciona sin hacer ninguna modificación. Sin embargo, hay algunos detalles que quizás tengas que modificar en tu código. Abajo encontrarás alguno de estos detalles.
Adicionalmente, es muy recomendable que repliegues (desinstales) tu vieja aplicación del servidor de aplicaciones, y la vuelvas a desplegar. Es decir, borra la vieja aplicación de la carpeta webapps del Tomcat, antes de desplegar una nueva versión de ésta basada en OX4m6, así nos aseguramos de que los viejos jars de JPA e Hibernate se han borrado. Borra también las carpetas .dist de tu workspace o workspace.dist.

Referencias @ManyToOne inexistentes usadas como @Id ya no están soportadas (Hibernate 3.6)

Hibernate 3.6 no soporta referencias @ManyToOne inexistentes usada como @Id. Es decir, si tienes una entidad con las siguientes claves:
public class Albaran {
 
  @Id @Column(length=5)
  private int numero;
 
  @Id @ManyToOne(fetch=FetchType.LAZY)
  private TipoAlbaran tipo;  // El tipo ha de existir en la base de datos
  ...
}
En este caso el TipoAlbaran referenciado tiene que existir siempre en la base de datos.
Realmente, este es un caso muy raro que sólo te encontrarás cuando trabajes contra bases de datos legadas diseñadas por programadores la era pre-RDBMS (como los programadores RPG). Ellos a veces usan claves que incluyen referencias a otras tablas, y cuando esas referencias no existen ponen ceros en los campos. Si te encuentras con este caso puedes resolverlo de alguna de las siguientes maneras:

Para poder asignar una entidad ya existente ésta ha de ser 'manejada' (Hibernate 3.6)

Es decir, en las versiones previas de Hibernate podías escribir:
Albaran albaran = new Albaran();
TipoAlbaran tipoAlbaran = new TipoAlbaran(); // Creamos un nuevo TipoAlbaran
                                             // en lugar de buscarlo
tipoAlbaran.setNumero(66); // El TipoAlbaran 66 ya existe en la base de datos
albaran.setTipo(tipoAlbaran);
...
XPersistence.getManager().persist(albaran);
Pero, esto no funciona con Hibernate 3.6, en su lugar has de escribirlo lo siguiente:
Albaran albaran = new Albaran();
TipoAlbaran tipoAlbaran = XPersistence.getManager()
  .find(TipoAlbaran.class, 66); // Lo buscamos
albaran.setTipo(tipoAlbaran);
XPersistence.getManager().persist(albaran);

Entidad con solo una referencia @ManyToOne como clave (Hibernate 3.6)

Con versiones anteriores de Hibernate podías escribir el siguiente código en tu entidad:
@Entity
@IdClass(PersonaContactoClienteKey.class)
public class PersonaContactoCliente {
 
  @Id @ManyToOne(fetch=FetchType.LAZY)
  private Cliente cliente;
 
  // No más campos @Id
 
  ...
 
}
Y la referencia de esta forma:
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="CUSTOMERCONTACT") // Sin el atributo referencedColumnName
private PersonaContactoCliente personaContactoCliente;
Y esto funcionaba. Sin embargo, con Hibernate 3.6 esto no funciona. Afortunadamente, hay una forma de conseguir el mismo efecto. Escribe tu entidad de la siguiente forma:
@Entity // @IdClass ya no se usa
public class PersonaContactoCliente
  implements java.io.Serializable { // Tiene que implementar Serializable
 
  @Id @ManyToOne(fetch=FetchType.LAZY)
  private Cliente cliente;
 
  // No más campos @Id
 
  ...
 
}
Y la referencia de esta forma:
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumns({
  @JoinColumn(name="CUSTOMERCONTACT",
    referencedColumnName="CUSTOMER_NUMBER") // referencedColumnName es obligatorio
})
private PersonaContactoCliente personaContactoCliente;

Type de Hibernate CharBooleanType no funciona (Hibernate 3.6)

CharBooleanType (y algunos otros types de Hibernate) ha sido marcado como obsoleto (deprecated), es más, no funcioa bien en Hibernate 3.6. Si tienes algún type que extienda de CharBooleanType, tienes que reescribirlo para extender de AbstractSingleColumnStandardBasicType. Mira SiNoType en el paquete org.openxava.types.

Entidades con @DiscriminatorColumn arroja errores (Hibernate 3.6)

Las entidades que contengan discriminador que sea parte de la clave, arrojarán error de campo duplicado. Suponga que tiene una entidad anotada de la siguiente manera:
@Entity
@Table(name = "`TABLAS`")
@DiscriminatorColumn(name="ID",
        discriminatorType=DiscriminatorType.STRING,
        length=20)
 
Hibernate 3.4 correrá sin problemas, pero la versión 3.6 (y me parece que la 3.5 también) les arrojará el error de campo duplicado. Para corregir esto debe utilizar una anotación dependiente de Hibernate @DiscriminatorOptions de la siguiente forma:
@Entity
@Table(name = "`TABLES`")
@DiscriminatorColumn(name="ID",
        discriminatorType=DiscriminatorType.STRING,
        length=20)
@DiscriminatorOptions(insert = false) // Anotacion dependiente de Hibernate
 
Y debe funcionar correctamente.

Método getProperty() renombrado en ModuleTestBase

El método getProperty() de ModuleTestBase ha sido renombrado como getXavaJUnitProperty(). Por tanto, si lo usas en tu prueba has de renombrar la llamada al método, como sigue:
String host = getProperty("host"); // Hasta v4m5
// Tiene que cambiarse por
String host = getXavaJUnitProperty("host"); // A partir de v4m6
Este cambio fue necesario para permitir usar Groovy al escribir pruebas JUnit.

Para migrar de OpenXava 4m4 a OpenXava 4m5

El controlador Navigation no se añade automáticamente

Hasta ahora el controlador Navigation (con las acciones anterior - inicio - siguiente en modo detalle) era añadido automáticamente a todos los módulos con detalle y lista. A partir de ahora, este controlador ya no se añadirá implícitamente. Esto no es un problema ya que Typical lo exteniende, pero si tienes un módulo con detalle - lista sin controlador Typical, en ese caso has de añadir Navigation explícitamente:
<modulo nombre="CambiarPrecioProducto">
  <modelo nombre="Producto"/>
  <controlador nombre="Navigation"/>  <!-- Has de añadir esto -->
  <controlador nombre="CambiarPrecioProducto"/>
</modulo>

Nuevo modo split (partido) - Cambios en jUnit

Además de detalle y lista, ahora tenemos un nuevo modo, split (partido), que permite mostrar la lista y el detalle al mismo tiempo. Esta funcionalidad no produce ninguna incompatibilidad a nivel de aplicación, pero si usas assertActions() en tus pruebas puede que tengas que añadir esta nueva acción:
String [] listActions = {
  "Print.generatePdf",
  "Print.generateExcel",
  "CRUD.new",
  "CRUD.deleteSelected",
  "Mode.detailAndFirst",
  "Mode.split", // HAS DE AÑADIR ESTO
  "List.filter",
  "List.customize",
  "List.orderBy",
  "List.viewDetail",
  "List.hideRows",
};
assertActions(listActions);
Si no te gusta este nuevo modo split, lo puedes quitar de tu applicación añadiendo la siguiente entrada en xava.properties:
defaultModeController=DetailList
En este caso el controlador de modo ya no es Mode sino DetailList, esto implica que has de cambiar tu pruebas junit:
// execute("Mode.list"); // NO si defaultModeController=DetailList en xava.properties
execute("DetailList.list"); // SÍ si defaultModeController=DetailList en xava.properties

Nueva acción CRUD.deleteRow - Cambios en jUnit

La acción CRUD.deleteSelected ha sido divida en CRUD.deleteSelected y CRUD.deleteRow. Si usas CRUD.deleteSelected con el argumento row, has de cambiarla por CRUD.deleteRow:
// execute("CRUD.deleteSelected", "row=2"); // NO, desde 4m5
execute("CRUD.deleteRow", "row=2"); // SI
Además, dado que CRUD.deleteRow está disponible por defecto en todos lo módulos, si usas assertActions() en tus pruebas puede que tengas que añadirla a la lista de acciones.

La vista (View) no es editable por defecto

A partir de ahora cuando se inicializa un módulo el objeto View no es editable. Esto no es un gran problema porque las acciones para nuevo y buscar establecen el estado correcto de editable en la vista. Pero si tienes una acción de nuevo o buscar personalizada puede que necesites modificarla para establecer el estado de editable explicitamente:
public class MiAccionBuscar extends ViewBaseAction {
 
  public void execute() throws Exception {
    ...
    getView().setKeyEditable(false);  // Has de llamar a setKeyEditable()
    getView().setEditable(true);      // y setEditalbe() explicitamente
    ...
  }
 
}

Para migrar de OpenXava 4m3 a OpenXava 4m4

CRUD.search ahora usa un diálogo - Cambios en jUnit

La acción CRUD.search ahora usa un diálogo para introducir los datos de búsqueda. Esto implica que todas tus pruebas junit que usen CRUD.search fallarán. Es decir, si tienes una prueba como la siguiente:
setValue("codigo", "1");
execute("CRUD.search");
assertValue("descripcion", "Número uno");
No funcionará. Has de reescribirla. Para hacerlo, tienes 2 opciones. La primera es adaptar tu prueba al nuevo comportamiento de la acción CRUD.search:
execute("CRUD.search"); // Muestra un diálogo
setValue("codigo", "1");
execute("Search.search"); // Hace la búsqueda y cierra el diálogo
assertValue("descripcion", "Número uno");
La segunda es cambiar "CRUD.search" por "CRUD.refresh", ya que la vieja CRUD.search ha sido renombrada como CRUD.refresh:
setValue("numero", "1");
execute("CRUD.refresh"); // En lugar de CRUD.search
assertValue("descripcion", "Número uno");
Además, dado que CRUD.refresh está disponible por defecto en todos lo módulos, si usas assertActions() en tus pruebas puede que tengas que añadirla a la lista de acciones.

Para migrar de OpenXava 4m2 a OpenXava 4m3

MapFacade.getValues() incluye el nombre del modelo en el resultado

MapFacade.getValues() ahora incluye el nombre del modelo en el resultado, con una entrada con la clave MapFacade.MODEL_NAME. Si usas la clases estándar de OpenXava (como View o PropertiesManager) todo funcionará bien, pero si tienes código personalizado puede ser que falle por culpa de esta nueva entrada inexeperada. En este caso quita la entrada de los valores, de esta forma:
Map valores = MapFacace.getValues("Persona", clave, miembros);
valores.remove(MapFacade.MODEL_NAME); // Puede que necesites esta línea

Método Classes.getSimpleName() eliminado

El método getSimpleName() de Classes ha sido eliminado. Usa getSimpleName() de Class available de Java 5 en su lugar.
Cambia esto:
Classes.getSimpleName(laClase);
por esto otro:
laClase.getSimpleName();

Para migrar de OpenXava 4m1 a OpenXava 4m2

Atributos mostrar-dialogo y ocultar-dialogo quitados de <accion/>

La forma declarativa de mostrar un diálogo ha sido sustituida por una programática en v4m2. La nueva forma es más flexible y requiere menos código, aunque la razón real para hacer este cambio es que la forma declarativa obliga al desarrollador a tocar controladores.xml cada vez que se hace una mejora en las acciones estándar con los diálogos. Es decir, con la forma declarativa muchas mejoras en OX requerirían muchas instrucciones de migración para que el desarrollador pueda actualizar su aplicación. Con el nuevo enfoque programático, el desarrollador puede actualizarse su versión de OX y disfrutar, sin tener que tocar su aplicación.
La mala noticia es que has de reescribir tu código con diálogos, ahora en vez de marcar tu acción con mostrar-dialogo y ocultar-dialogo, tienes que usar los métodos showDialog() y closeDialog(). Compara la nueva forma con la vieja para más detalles.

Las colecciones usan diálogos para editar, ver y añadir detalles - Cambios en acciones

Todas las acciones que extienden de CollectionBaseAction o CollectionElementViewBaseAction mantienen su comportamiento original, por tanto no necesitas hacer ningún cambio en la mayoría de tus acciones de colección. Pero, si tienes alguna acción de detalle que extienda directamente de ViewBaseAction quizás tengas que cambiar la forma de acceder a la vista padre. Recuerda que ahora estás dentro de un diálogo:
public class MiAccionDetalleParaColeccion extends ViewBaseAction  {
 
    public void execute() throws Exception {
        ...
        getView().setValue("nombre", "Pepe"); // Ahora getView() es la vista del diálogo
        getPreviousView().setValue("nombre", "Pepe"); // getPreviousView() es la vista
                                                      // que ha abierto el diálogo
        closeDialog();
    }
}
 
Es decir, quizás tengas que cambiar getView() por getPreviousView() en alguna de tus acciones.

Las colecciones usan diálogos para editar, ver y añadir detalles - Cambios en jUnit

Esto no afecta al código de tu aplicación, pero dado que el comportamiento de las colecciones ha cambiado, has de adaptar tu pruebas junit. La principal diferencia es que el usuario ahora usa un diálogo para editar la línea de detalle de la colección, por tanto el resto de las acciones y valores de la interfaz de usuario principal no están disponibles, ya que se usa un diálogo modal.
Ahora los miembros de la vista de detalle están en la vista raíz, por tanto tienes que quitar el prefijo de colección cuando referencias miembro del elemento de la colección:
// lineas es el nombre de la colección
setValue("lineas.cantidad", "6");  // Ahora ¡INCORRECTO! Has de quitar 'lineas'
setValue("cantidad", "6"); // ¡CORRECTO! Sin nombre de colección
También las acciones disponible al editar el elemento de una colección (por ende dentro de un diálogo) no usan ningún argumento:
execute("Collection.save", "viewObject=xava_view_section1_lineas"); // ¡INCORRECTO!
execute("Collection.save"); // ¡CORRECTO!
Si quieres acceder a las acciones o miembro de la vista principal, has de cerras el diálogo primero:
execute("Factura.editarLinea", "row=1,viewObject=xava_view_section1_details");
assertValue("cantidad", "234");
closeDialog(); // Necesario antes de ejecutar CRUD.save
execute("CRUD.save");
Al grabar el elemento de una colección el diálogo se cierra, por eso si quieres añadir otro detalle has de abrir otra vez el diálogo:
execute("Collection.save"); // Esto cierra el diálogo
execute("Collection.new", // Es necesario llamar a 'new' de nuevo, para abrir el diálogo
  "viewObject=xava_view_section1_lineas");
En las colecciones anidadas has de cambiar el valor del argumento viewObject de las acciones de fila, otra vez por causa de que está dentro de un diálogo que es la vista raíz:
execute("Collection.new",
  "viewObject=xava_view_lugaresEntrega_recepcionistas"); // ¡INCORRECTO!
execute("Collection.new",
  "viewObject=xava_view_recepcionistas"); // ¡CORRECTO! Solo el nombre de la
                                          // última colección anidada
Esto no solo aplica a viewObject sino también a otras referencias a la colección anida en el argumento de la acción. Fíjate en el siguiente ejemplo:
// ¡INCORRECTO!: Usando "lugaresEntrega.recepcionistas", el nombre calificado
setConditionValues("lugaresEntrega.recepcionistas", new String[] { "J" } );
execute("List.filter", "collection=lugaresEntrega.recepcionistas");
assertCollectionRowCount("lugaresEntrega.recepcionistas", 1);
assertValueInCollection("lugaresEntrega.recepcionistas", 0, 0, "JUAN");
 
// ¡CORRECTO!: Usando "recepcionistas", el nombre simple
setConditionValues("recepcionistas", new String[] { "J"} );
execute("List.filter", "collection=recepcionistas");
assertCollectionRowCount("recepcionistas", 1);
assertValueInCollection("recepcionistas", 0, 0, "JUAN");
En general, si tu prueba falla trata de quitar el nombre de colección como prefijo del nombre de miembro, argumento de acción, etc.

Acción de fila para las colecciones de entidades es por defecto view y no edit

No has de cambiar el código de la aplicación, solo el código de pruebas:
// Solo para colecciones de entidades sin @AsEmbedded
execute("Collection.edit",
  "row=0,viewObject=xava_view_clientes"); // ¡INCORRECTO! 'edit' ya no se usa
execute("Collection.view",
  "row=0,viewObject=xava_view_clientes"); // ¡CORRECTO! Ahora es la acción
                                          // 'view' la que se usa
Esto también implica que los elementos de la vista no tienen editable las propiedades clave y no tienen acción para borrar. Puede ser que tengas que adaptar tu prueba:
// Dentro de un diálogo que visualiza el elemento de colección
assertEditable("numero"); // ¡INCORRECTO! Los campos clave no son editable
execute("Collection.remove"); // ¡INCORRECTO! 'remove' no está disponible
Este cambio no aplica a colecciones con @AsEmbeddable, CascadeType.REMOVE o CascadeType.ALL.

Para migrar de OpenXava 3.1.4 a OpenXava 4m1

BaseAction implementa IModuleContextAction

BaseAction ahora implementa IModuleContextAction, por tanto si alguna de tus acciones lo implementa has de reescribir el método setContext() llamando a super.setContext(). De esta manera:
public class MiAccion extends BaseAction implements IModuleContextAction {
    public void setContext(ModuleContext context) {
        super.setContext(context);  // Tienes que añadir esta línea
        this.context = context;
    }
}
Otra opción es quitar el implements IModuleContextAction y el método setContext(), y usar el método protegido getContext() de BaseAction, para acceder al contexto.

Objeto de sesión xava_currentReferenceLabel eliminado

Nota: Este cambio no es necesario si actualizas directamente a 4m2 o superior, porque desde 4m2 inyectar usando <usa-objeto /> en una propiedad inexistente no falla, sino que produce un simple mensaje de advertencia.
El objeto de sesión xava_currentReferenceLabel ya no se usa; por tanto ha sido eliminado de default-controllers.xml. Esta objeto se usaba por las acciones de búsqueda de las referencias, por tanto si tienes una acción para buscar referencias propia has de quitar la referencia a xava_currentReferenceLabel en tu controladores.xml, tal como muestra el siguiente código:
<controlador nombre="MiReferencia">
    <accion nombre="buscar" oculta="true"
        mostrar-dialogo="true"
        clase="org.openxava.test.acciones.BuscarMiReferencia"
        imagen="images/search.gif">
        <usa-objeto nombre="xava_view"/>
        <usa-objeto nombre="xava_referenceSubview"/>
        <!-- Esta línea se tiene que quitar
        <usa-objeto nombre="xava_currentReferenceLabel"/>
        -->
        <usa-objeto nombre="xava_tab"/>
    </accion>
</controlador>
También es conveniente para las acciones de búsqueda y otras acciones de referencias usar mostrar-dialogo="true" (mostrar-dialogo ha sido quitado en v4m2) para mostrar la búsqueda en un diálogo, tal como hacen las acciones de búsqueda estándar de OX.

Para migrar de OpenXava 3.1.3 a OpenXava 3.1.4

Esquema de tabla de AccessTracking cambiado

En el proyecto AccessTracking el esquema de la tabla para registrar los accesos ha cambiado:
Es necesario cambiar nuestras tabla actual si queremos actualizar a AccessTracking 3.1.4
Este cambio se ha hecho para que AccessTracking pueda funcionar en bases de datos que no soporten USER como nombre de columna.

Para migrar de OpenXava 3.1.1 a OpenXava 3.1.2/3.1.3

Sin consideraciones.

Para migrar de OpenXava 3.1 a OpenXava 3.1.1

La generación de ids para elementos HTML ha cambiado para soportar multimódulo por página

Para poder soportar varios módulos en la misma página de un portal; OX, desde v3.1.1, cambia la forma en que los ids de los elementos HTML son generados. Esto no tiene efecto en el código de nuestra aplicación ya que la manipulación directa de elementos HTML es algo raro en una aplicación OpenXava típica. Sin embargo, necesitaremos hacer algunos cambios leves en nuestras pruebas junit.
Cuando usemos xava.keyProperty como argumento en una acción dentro de la prueba junit, ya no usaremos xava.ModelName como prefijo nunca más. Es decir, hemos de cambiar:
execute("Albaran.generarNumero", "xava.keyProperty=xava.Albaran.numero");
por
execute("Albaran.generarNumero", "xava.keyProperty=numero");
Tan solo eliminamos xava.Albaran en este caso.
Para evitar una migración demasiado laboriosa OpenXava todavía soporta el viejo estilo para todas las acciones del controlador Reference.
Además, si inspeccionamos directamente el documento HTML usando los ids, hemos de decorarlos con el método decorateId(). Es decir, si tenemos algo como esto:
HtmlImage imagen = (HtmlImage)
  page.getHtmlElementsByName("xava.Formula.ingredientes.imagen").get(0);
Necesitamos cambiarlo por el siguiente código:
HtmlImage imagen = (HtmlImage)
  page.getHtmlElementsByName(decorateId("ingredientes.imagen")).get(0);
Aquí usamos decorateId(). Fijémonos también en que hemos quitado el prefijo xava.Formula.

Para migrar de OpenXava 3.0.3 a OpenXava 3.1

El código JavaScript de los editores tiene que moverse desde los JSPs a custom-editors.js

Si alguno de nuestros editores personalizados define funciones JavaScript dentro del JSP, hemos de moverlos a un archivo con el nombre custom-editors.js (puede que necesitemos crearlo) en la carpeta web/xava/js de nuestro proyecto. Nota: A partir de v4m3 se pude poner el código JavaScript para los editore en cualquier archivo, no importa el nombre, en la carpeta web/xava/editors/js. De esta forma puedes tener uno o más archivos por cada editor, y es puedes incluir librerías de tercero fácilmente.
Es decir, si tenemos un editor llamado mapaGoogleEditor.jsp con una función JavaScript llamada muestraMap(), justo de esta forma:
<script>
function muestraMapa(v) {
  ...
}
</script>
 
<!-- Aquí código JSP -->
Hemos de moverla a custom-editors.js, de esta forma:
if (openxava == null) var openxava = {};
if (openxava.editors == null) openxava.editors = {};
 
// mapaGoogleEditor
if (openxava.editors.mapaGoogle== null) openxava.editors.mapaGoogle= {};
openxava.editors.mapaGoogle.muestraMapa = function(v){
  ...
}
 
Ahora dentro de nuestro editor en vez de llamar a la función de esta forma:
<input ... onclick="muestraMapa(valor)"/>
hemos de hacerlo calificando la función:
<input ... onclick="openxava.editors.mapaGoogle.muestraMapa(valor)"/>

Llamar al método View.refreshCollections() cuando se modifiquen los datos de una colección

Desde OpenXava 3.1 solo los datos modificados se refrescan en la vista. Cuando el usuario pulsa en una acción de una colección la colección se refresca automáticamente, pero si nuestra acción está fuera de la colección entonces no hay manera de saber si los datos de la colección se han modificado. En este caso necesitamos llamar explícitamente a View.refreshCollections(). Por ejemplo:
// No es una acción de una colección
public class TraducirTodosNombresTransportistas extends ViewBaseAction {
 
    public void execute() throws Exception {
        for (Iterator it=Transportista.findAll().iterator(); it.hasNext(); ) {
            Transportista t = (Transportista) it.next();
            t.traducir(); // El transportista se modifica,
                // estos datos se muestran en una colección de la vista
        }
        getView().refreshCollections(); // Para refrescar los datos de
            // las colecciones visualizadas
    }
 
}
Es decir, quizás necesitemos añadir getView().refreshCollections() si los datos de la colección no se refrescan después de ejecutar nuestra acción.

Más librerías necesarias en MANIFEST.MF (solo para EJB2)

Hemos de editar el archivo build/ejb/META-INF/MANIFEST.MF, y añadir los siguientes archivos ./lib/slf4j-api.jar ./lib/slf4j-jdk14.jar ./lib/javassist.jar a la lista de jars.
Esto solo aplica si estamos usando EJB (generando un EAR). Mirar OpenXavaTest/build/ejb/META-INF/MANIFEST.MF para una lista de jars completa y actualizada.

Para migrar de OpenXava 3.0.2 a OpenXava 3.0.3

HttpUnit reemplazado por HtmlUnit para las pruebas junit usando ModuleTestBase

HttpUnit ha sido reemplazado por HtmlUnit para las pruebas junit basadas en ModuleTestBase. La razón principal es el precario soporte de AJAX que ofrece HttpUnit.
La mayoría de nuestras pruebas junit basadas en ModuleTestBase seguirán funcionando sin tocarlas. HtmlUnit funciona como un navegador de verdad, permitiendo probar mejor nuestras aplicaciones, pero hay algunos pequeños cambios que puede que necesitemos hacer en algunas de nuestras pruebas junit con algún caso especial.
Estos son algunos de los cambios en ModuleTestBase:

Es obligado usar argumentos exactos para execute()

Es decir, si escribimos en nuestra prueba:
execute("Reference.search", "keyProperty=xava.Transportista.almacen.codigoZona");
y el vínculo en la pagína tiene keyProperty=xava.Transportista.almacen.codigo, es decir, no es exactamente igual; en el caso de HttpUnit funciona, pero en el caso de HtmlUnit no. No podemos ejecutar acciones que no estén disponible al usuario mediante botones o vínculos, además nuestra prueba tiene que ejecutar la acción exactamente de la misma forma que lo hace el usuario.

Los métodos allowDuplicateSubmit() y click() han sido eliminados

Hasta ahora, cuando queríamos simular un click del usuario necesitábamos un código como este:
allowDuplicateSubmit();
click("MiControlador.miAccion");
Llamar a allowDuplicateSubmit() es obligado antes de usar click(). El método click() lanza los eventos asociados al botón o vínculo pero no funciona bien en muchos casos. Desde ahora, usando HtmlUnit, el execute() simula a click(), y lo hace bien, por tanto click() y allowDuplicateSubmit() ya no son necesarios. Si tenemos un código como el de arriba podemos sustituirlo por algo así:
execute("MiControlador.miAccion");

El método getForm() devuelve un HtmlForm

El método protegido getForm() de ModuleTestBase que antes devolvía un WebForm de HttpUnit ahora devuelve un HtmlForm de HtmlUnit. Si lo estamos usando en alguna prueba hemos de reescribirla. Afortunadamente este método es usado ráramente.

El método getConversation() reemplazado por getWebClient()

El método protegido getConversation() de ModuleTestBase que antes devolvía WebConversation() de HttpUnit ha sido reemplazado por el método getWebClient() de HtmlUnit que devuelve un WebClient. Si lo estamos usando en alguna prueba hemos de reescribirla. Afortunadamente este método es usado ráramente.

Uso más fácil de setConditionValue

Antes teníamos que escribir:
String [] condicion= { " ", "", "", "V" };
setConditionValues(condicion);
Cuando queríamos rellenar el cuarto elemento y el segundo era un combo (un enum o boolean). Notemos que necesitabamos poner un espacio en blanco como primer elemento, realmente en todos los que había antes del combo. Este truco, necesario por culpa de HttpUnit, ya no hace falta más. Ahora podemos escribir:
String [] totalCondition = { "", "", "", "V" };
setConditionValues(totalCondition);
Sin preocuparnos por poner espacios en blanco, aunque si los ponemos también funciona.

Para migrar de OpenXava 3.0.1 a OpenXava 3.0.2

Mensaje de objeto no encontrado incluye valores de la clave de búsqueda (para pruebas junit)

Esto puede requerir algún ligero cambio en nuestras pruebas junit. Tenemos que cambiar un código como este en nuestra prueba:
assertError("No encontrado el objeto de tipo Factura con es clave");
por
assertError("No encontrado el objeto de tipo Factura con clave Año:2008, Número:1");

Ya no se usa Hibernate para las preferencias de usuario

Ahora se usa Java Preferences para almacenar las preferencias de usuario. OpenXavaDS y openxava-db ya no son necesarios.
Por tanto, hemos de borrar TabUserPreferences.hbm.xml y openxava-hibernate.cfg.xml de la carpeta persistence de nuestro proyecto.

Para migrar de OpenXava 3.0 a OpenXava 3.0.1

Las anotaciones de validación ahora son restricciones de Hibernate Validator

@Required, @PropertyValidator y @EntityValidator están definidas desde 3.0.1 como restricciones Hibernate Validator. Esto quiere decir que cuando grabamos usando directamente la api de JPA, estas validaciones se aplicarán.
Es decir, si tenemos una entidad como esta:
@Entity
public class Cliente {
 
    @Required
    private int codigo;
 
    @Required
    private String nombre;
 
    @Required
    private String observaciones;
 
    ...
 }
Y ejecutamos el siguiente código:
Cliente c = new Cliente();
c.setCodigo(1);
c.setNombre("JUANITO");
// Dejamos la propiedad observaciones vacía
XPersistence.getManager().save(c);
XPersistence.commit();
El código funciona con OX3.0, pero falla con OX3.0.1, porque en OX3.0.1 la restricción @Required se aplica cuando grabamos usando JPA. En OX3.0, y anteriores, la validación se aplicaba solo cuando usábamos OpenXava (con MapFacade, o las acciones estándar de OX).
Para arreglar este caso, por ejemplo, solo necesitamos llenar la propiedad observaciones antes de grabar.

Ligera mejora en la acción 'new' de CRUD

Ahora la acción new activa automáticamente la sección inicial. Esto puede romper algunas pruebas junit. Por ejemplo, si tenemos este código:
execute("Sections.change", "activeSection=2");
...
execute("CRUD.new");
setValue("propiedadEnSeccion2", "el valor"); // Esta propiedad está en la sección 2
En este caso tenemos que volver a la sección 2 explicitamente:
execute("Sections.change", "activeSection=2");
...
execute("CRUD.new");
// Tenemos que añadir la siguiente línea, porque después de 'new' estamos en la sección 0
execute("Sections.change", "activeSection=2");
setValue("propiedadEnSeccion2", "el valor"); // Esta propiedad está en la sección 2
 

Para migrar de OpenXava 2.2.5 a OpenXava 3.0

El proveedor de persistencia por defecto es JPA

Desde la v3.0 OpenXava usa JPA por defecto para la persistencia. Si quieres seguir usando Hibernate como proveedor de persistencia en tu aplicación pon la siguiente línea en el archivo xava.properties de tu proyecto:
persistenceProviderClass=org.openxava.model.impl.HibernatePersistenceProvider

MapFacade ya no lanza RemoteException

Ahora los método de MapFacade no lanzan RemoteException sino SystemException, que es una excepción runtime.
Esto tiene poca repercusión en tu código, pero si tienes algo así:
try {
    MapFacade.validate("Factura", valores);
}
catch (RemoteException ex) {
    ...
}
Entonces tendrás que cambiar la RemoteException por una SystemException:
try {
    MapFacade.validate("Factura", valores);
}
catch (SystemException ex) {
    ...
}
Además, XavaException ahora es una excepción runtime. Pero esto no implica ningún cambio en tu código.

Para migrar de OpenXava 2.2.4 a OpenXava 2.2.5

MapFacade no es autocommit a partir de ahora

Hasta ahora, cuando escribiamos:
MapFacade.create("Cliente", valoresCliente);
MapFacade.create("Factura", valoresFactura);
Estas dos líneas eran dos transacciones. Si la creación de la factura fallaba el cliente se grababa. Es decir, MapFacade tenía una política de autocommit.
Desde ahora MapFacade no es autocommit por defecto, es decir, el caso de arriba tendrá solo una transacción, confirmada por OX al final de la acción o el test. Ahora, si la creación de la factura falla la creación del cliente no se producirá.
Esto puede alterar ligeramente el comportamiento de nuestras acciones en caso de fallo, pero solo si nuestras ascciones hacen varias llamadas a MapFacade. Si queremos preservar el comportamiento anterior tenemos dos opciones.
Primera opción: añadir la siguiente línea a nuestro archivo properties/xava.properties:
mapFacadeAutoCommit=true
Segunda opción: confirmar la acción manualmente. Por ejemplo, el código de arriba se puede escribir de esta forma:
MapFacade.create("Cliente", valoresCliente);
MapFacade.commit();
MapFacade.create("Factura", valoresFactura);
MapFacade.commit();

Para migrar de OpenXava 2.2.3 a OpenXava 2.2.4

El esquema para table de imagenes del estereotipo GALERIA_IMAGENES

Ahora el esquema para la table de imagenes se especifica separadamente, es decir,
Now the schema for image table is specified specified separately, that is, ante escribiamos esto en nuestro archivo de propiedades de configuración:
images.table=XAVATEST.IMAGES
Ahora hemos de escribir:
images.schema=XAVATEST
images.table=IMAGES

Para migrar de OpenXava 2.2.2 a OpenXava 2.2.3

Las etiquetas del modo lista y colecciones son calificadas (para las pruebas junit)

Las etiquetas pare el modo lista y las colecciones ahora son calificadas, es decir si tenemos una propiedad cliente.nombre, antes la etiqueta era Nombre, y ahora es Nombre de Cliente. Esto puede afectar nuestras pruebas junit, es decir, si tenemos:
assertLabelInList(2, "Nombre"); // de cliente.nombre
ahora tenemos que escribir:
assertLabelInList(2, "Nombre de Cliente"); de cliente.nombre

Esquema de tabla de AccessTracking cambiado

En el proyecto AccessTracking el esquema de la tabla para registrar los accesos ha cambiado:
Es necesario cambiar nuestras tabla actual si queremos actualizar a AccessTracking 2.2.3
Este cambio se ha hecho para que AccessTracking pueda funcionar en bases de datos que no soporten TABLE, DATE y TIME como nombre de columna.

Para migrar de OpenXava 2.2.1 a OpenXava 2.2.2

Sin consideraciones.

Para migrar de OpenXava 2.2 a OpenXava 2.2.1

MoneyFormatter (para pruebas junit)

Un formateador de dinero es aplicado por defecto para formatear o analizar todos los valores con el estereotipo DINERO, ahora toda la información de tipo dinero es siempre visualizada usando dos cifras decimales. Por tanto, hemos de adaptar nuestras pruebas junit, cambiando líneas como esta:
assertValue("importe", "20");
por algo así:
assertValue("importe", "20.00");
O, si así lo preferimos podemos usar la vieja forma de formatear, solo hemos de desactivar el formateador o definir el nuestro propio editando nuestro archivo editores.xml.

Acción 'Mode.list" no está disponible cuando el usuario navega a otra vista (para pruebas junit)

Cuando el usuario navega a otra vista (por ejemplo para crear o modificar una referencia) el vínculo para ir al modo lista ahora no está presente. Quizás necesites cambiar tu prueba junit:
Por ejempo, en este código junit:
execute("Reference.createNew", "model=Family2,keyProperty=xava.Product2.family.number");
assertAction("Mode.list"); // Desde 2.2.1 falla
El assertAction("Mode.list") se tiene que quitar

Para migrar de OpenXava 2.1.5 a OpenXava 2.2

El comportamiento por defecto para las colecciones de entidades cambia

Ahora, cuando el usuario pulsa en 'Añadir' en una colección de entidades, va a una lista donde puede escoger varias entidades para añadir. Esto puede causar que nuestro actual código JUnit falle. Necesitamos hacer unas simples modificaciones; sencillamente cambiar código como este en nuestras pruebas JUnit:
execute("Collection.new", "viewObject=xava_view_customers");
setValue("customers.number", getCustomerNumber2());
assertValueIgnoringCase("customers.name", getCustomer2().getName());
assertCollectionRowCount("customers",0);
execute("Collection.save", "viewObject=xava_view_customers");
assertCollectionRowCount("customers",1);
por este otro:
assertCollectionRowCount("customers",0);
execute("Collection.add", "viewObject=xava_view_customers");
assertValueInList(5, 0, getCustomer2().getName());
execute("AddToCollection.add", "row=5");
assertMessage("1 element(s) added to Customers of Seller");
assertCollectionRowCount("customers",1);
Además, el usuario ahora puede añadir varias entidades a la vez, esto es, un código como este:
execute("Collection.new", "viewObject=xava_view_customers");
setValue("customers.number", getCustomerNumber1());
assertValueIgnoringCase("customers.name", getCustomer1().getName());
assertCollectionRowCount("customers", 0);
execute("Collection.save", "viewObject=xava_view_customers");
assertMessage("Customer associated to Seller");
 
assertCollectionRowCount("customers", 1);
setValue("customers.number", getCustomerNumber2());
assertValueIgnoringCase("customers.name", getCustomer2().getName());
execute("Collection.save", "viewObject=xava_view_customers");
assertCollectionRowCount("customers",2);
se puede escribir así:
execute("Collection.add", "viewObject=xava_view_customers");
assertValueInList(4, 0, getCustomer1().getName());
assertValueInList(5, 0, getCustomer2().getName());
checkRow(4);
checkRow(5);
execute("AddToCollection.add");
assertMessage("2 element(s) added to Customers of Seller");
assertCollectionRowCount("customers",2);

El comportamiento por defecto para las colecciones de agregados cambia

Ahora, cuando un detalle de una collección se graba, la vista del detalle no se oculta, esto puede causar que nuestro actual código JUnit falle. Necesitamos hacer unas simples modificaciones; sencillamente cambiar código como este en nuestras pruebas JUnit:
execute("Collection.save", "viewObject=xava_view_section1_details");
execute("Collection.new", "viewObject=xava_view_section1_details"); // A borrar
por este otro:
execute("Collection.save", "viewObject=xava_view_section1_details");
Es decir, borrar la llamada a "Collection.new", porque despues de grabar el detalle, la acción "new" se ejecuta automáticamente, así la interfaz de usuario está lista para introducir un nuevo detalle.

Para migrar de OpenXava 2.1.4 a OpenXava 2.1.5

No hay consideraciones.

Para migrar de OpenXava 2.1.3 a OpenXava 2.1.4

Nuevas acciones en colecciones (para pruebas junit)

Las collecciones tienen nuevas acciones disponibles para los usuarios, por tanto si comprobamos todas las acciones presentes en nuestras pruebas junit hemos de modificar nuestras pruebas para que tengas en cuenta las nuevas acciones.
Es decir, si tenemos algo como esto en nuestro código de prueba junit:
        String [] acciones = {
            "Navigation.previous",
            "Navigation.first",
            "Navigation.next",
            "CRUD.new",
            "CRUD.save",
            "CRUD.delete",
            "CRUD.search",
            "Collection.new",
            "Collection.removeSelected"
        };
        assertActions(acciones);
hemos de cambiarlo por:
    String [] acciones = {
            "Navigation.previous",
            "Navigation.first",
            "Navigation.next",
            "CRUD.new",
            "CRUD.save",
            "CRUD.delete",
            "CRUD.search",
            "Collection.new",
            "Collection.removeSelected",
            "List.filter",        // Nuevo
            "List.orderBy",       // Nuevo
            "List.customize",     // Nuevo
            "List.hideRows",      // Nuevo
            "Print.generatePdf",  // Nuevo
            "Print.generateExcel" // Nuevo
        };
        assertActions(acciones);

Tarea Ant generarPortlets eliminada

La tarea ant generarPorltets ha sido quitada de OpenXava/build.xml porque ahora es exactamente igual que generatePortlets. Por lo tanto, si en tu build.xml tienes algo como esto:
<target name="generarPortlets">
    <ant antfile="../OpenXava/build.xml" target="generarPortlets"/>
</target>
Tienes que cambiarlo por:
<target name="generarPortlets">
    <ant antfile="../OpenXava/build.xml" target="generatePortlets"/>
</target>

Para migrar de OpenXava 2.1 a OpenXava 2.1.3

Pruebas JUnit y claves sin valor interpretadas como cero

Desde 2.13 si una propieda clave de tipo int, long o short no tiene valor en la vista cuando es interpretada, es interpretada como nulo (sin valor), y no como cero. Esto no tiene efecto en el usuario final, pero posiblemente necesitemos cambiar algunas pruebas JUnit, por ejemplo
Since 2.1.3 if a property key of type int, long or short has no value in view when it is parsed is parsed with null (without value), and not as zero. This has no effect in final user, but possibly you need to modify some junit test. Por ejemplo si tenemos una prueba así:
public void testAlgo() throws Exception {
  assertValue("codigo", "");
  execute("MiControlador.miAccion"); // Esto no cambia el valor de 'codigo'
  assertValue("codigo", "0"); // porque OX interpreta una cadena vacía como un 0 (hasta 2.1.2)
  ...
}
Ahora hemos de escribirlo así:
public void testAlgo() throws Exception {
  assertValue("codigo", "");
  execute("MiControlador.miAccion"); // Esto no cambia el valor de 'codigo'
  assertValue("codigo", ""); // porque ahora (desde 2.1.3) OX interpreta cadena vacía como nulo
  ...
}

Para migrar de OpenXava 2.0.4 a OpenXava 2.1

Proyectos WebSphere

Si despliegas tus proyectos en WebSphere necesitas hacer algunos pequeños ajustes:
Primero, en el archivo hibernate/hibernate.cfg.xml de tu proyecto añade el siguiente código marcado en azul:
<session-factory>
  <property
    name="hibernate.connection.datasource">@datasource.prefix@/@datasource@</property>
  <property name="hibernate.dialect">@hibernate.dialect@</property>
  <property name="hibernate.jdbc.use_get_generated_keys">false</property>
  <property name="hibernate.show_sql">false</property>
  @hibernate.properties@
  ...
</session-factory>
Segundo, en tu archivo de configuración para websphere (por ejemplo websphere-as400.properties) has de añadir:
hibernate.properties=<property name="hibernate.transaction.manager_lookup_class">\n\
\t\t\torg.hibernate.transaction.WebSphereTransactionManagerLookup\n\
\t\t</property>\n\
\t\t<property name="transaction.factory_class">\n\
\t\t\torg.hibernate.transaction.JTATransactionFactory\n\
\t\t</property>

Otros cambios que requieren migración

Para migrar de OpenXava 2.0.3 a OpenXava 2.0.4

Parse de valores numéricos

Ahora los datos de tipo Number (Integer, BigDecimal, Short, etc) y Boolean (no boolean) son interpretados como nulo si en la interfaz de usuario están en blanco. Antes los campos numérico en blanco se interpretaban como 0. Este cambio no produce grandes incompatibilidades porque default-converters This change does not produce big incompatibility problems because default-converters.xml define las conversiones reales antes de grabar en la base de datos (que es lo que de verdad importa). Es decir, este cambio afecta solo a la visualización. Tus asuntos de incompatibilidad pueden ser:

Cambios en las API

Para migrar de OpenXava 2.0.2 a OpenXava 2.0.3

No se lanzan eventos al-cambiar cuando se busca

La guía de referencía (en la sección 7.5) dice que CRUD.searchByViewKey no lanza ningún evento al-cambiar, y CRUD.searchExecutingOnChange lanza todos los eventos al-cambiar. Pero por causa de un bug en ox2.0.2 (y anteriores) CRUD.searchByViewKey lanzaba al-cambiar de las claves en las referencias, y CRUD.searchExecutingOnChange no lanzaba al-cambiar de las claves en las referencias. Este problema ha sido resuelto, por la tanto si tienes código que confía en este comportamiento erroneo deberás adaptarlo.

Establece valor para referencías (en combos) con clave múltiple en las pruebas JUnit

Establece valor para referencías (en combos) con clave múltiple en las pruebas JUnit tiene que hacerse usando POJOs, el uso de claves primarias EJB2 no está soportado.
Ver documentación en Para migrar de OpenXava 1.2.1 a OpenXava 2.0 below.

Para migrar de OpenXava 2.0.1 a OpenXava 2.0.2

La acción Collection.hiddenDetail ha sido renombrada a Collection.hideDetail en controllers.xml. Debemos renombrar la acción dentro de nuestras pruebas junit.

Para migrar de OpenXava 2.0 a OpenXava 2.0.1

No hay consideraciones.

Para migrar de OpenXava 1.2.1 a OpenXava 2.0

Establece valor para referencías (en combos) con clave múltiple en las pruebas JUnit

Hasta ahora, para establecer valor a una referencía visualizada como lista-descripciones (como combo), y mapeada a la base de datos usando varias columnas, escribiamos:
PermisoConduccionKey clave = new PermisoConduccionKey();
clave.setType("C ");
clave.setLevel(1);
setValue("drivingLicence.KEY", clave.toString());
Pero, si usamos solo POJOs, sin clases 'Key', hemos de escribir:
PermisoConduccion clave = new PermisoConduccion();
clave.setType("C ");
clave.setLevel(1);
setValue("drivingLicence.KEY", clave.toString());
Es mejor usar la última forma, porque funciona con POJOs y EJBs.

Hibernate: Referencias con columnas no nula como clave foránea

En la versión EJB si tenemos una referencia a otra entidad cuya clave está compuesta por tipos primitivos, el código se genera de tal forma que no se graban nulos en la base de datos, aunque asignemos un nulo a la referencia.
En la versión Hibernate si asignamos nulo a una referencia, se graban valores nulos en la base de datos.
Por supuesto, el comportamiento de la versión Hibernate es más correcto, pero podemos hacer que en Hibernate se eviten los nulos en la base de dato, simplemente usando conversores en el mapeo de referencia (ver sección 6.3 de la guía de referencia).
Es decir, quizás necesitemos añadir algunos conversores a nuestra referencias para migrar nuestras aplicaciones de EJB2 a Hibernate.

Cambiar la sección activa

xava_activeSection ya no se usa para cambiar la sección activa. Ahora si queremos cambiar la sección activa tenemos que llamar al método setActiveSection de la vista deseada (org.openxava.view.View).

IAggragetOidCalculator

El método setContainerKey se ha renombrado a setContainer. Y su semántica también. Ahora se recibe el objeto contenedor en vez de la clave. De esta manera este calculador es consistente en la versión EJB2 y POJO (si clases para clave).

Para migrar de OpenXava 1.2 a OpenXava 1.2.1

Generación Hibernate

Ahora cuando la generación EJB se hace, la generación de código hibernate se realiza también (aunque la versión hibernate todavía no se soporta al 100%).
Aunque uses solo la versión EJB necesitas hacer una pequeña adaptación en tu proyecto:
El hibernate.cfg.xml ha de ser:
<!DOCTYPE hibernate-configuration PUBLIC
  "-//Hibernate/Hibernate Configuration DTD//EN"
  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 <hibernate-configuration>
  <session-factory>
   <property
    name="hibernate.connection.datasource">@datasource.prefix@/@datasource@</property>
   <property name="hibernate.dialect">@hibernate.dialect@</property>
   <property name="hibernate.show_sql">false</property>
  </session-factory>
</hibernate-configuration>
Adicionalmente tienes que incluir la propiedad hibernate.dialect en tus archivos de configuración:
hibernate.dialect=org.hibernate.dialect.HSQLDialect

Sintaxis XML de OpenXava

Para migrar de OpenXava 1.1 a OpenXava 1.2

Código generado

Ahora las interfaces remote de EJB tienen el sufijo Remote, y la interfaz de negocio generada para cada componente (por ejemplo ICliente) no contiene todos los métodos de la interface remota.
Esto es para permitir que la futura versión 2 de OpenXava pueda trabajar con EJB e Hibernate en el mismo projecto y a la vez.
Para adaptar el código hay que:
Para corregir los errores de sintaxis se tiene que hacer cambios como éste:
Cliente cliente = ClienteUtil.getHome().findByNombre("PEPE");
String nombre = cliente.getNombre();
Cambiarlo por:
ICliente cliente = ClienteUtil.getHome().findByNombre("PEPE");
String nombre = cliente.getNombre();
Si se usan métodos específicos de EJB hay que moldear a la interfaz remota:
Cliente cliente = ClienteUtil.getHome().findByNombre("PEPE");
ClienteKey key = cliente.getPrimaryKey();
Cambiarlo por:
ClienteRemote cliente = ClienteUtil.getHome().findByNombre("PEPE");
[[controllers_es#toc15|mostrar un diálogo]]ClienteKey key = cliente.getPrimaryKey();
Es decir, cambiar Cliente por ICliente cuando sea posible, de no serlo cambiarlo por CustomeRemote.

Pruebas JUnit

Otros

Para migrar de OpenXava 1.0 a OpenXava 1.1

APIs

Pruebas junit