openxava / documentación / Migración

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

Edita el archivo pom.xml de tu proyecto y cambia el valor de la propiedad openxava.version para que apunte a la última versión de OpenXava, así:

<properties>
    <openxava.version>7.4.1</openxava.version>
    ...
</properties>

Compila tu proyecto:


Si tu versión actual es la 6.x deberías seguir las instrucciones de la sección Para migrar de OpenXava 6.6.3 a OpenXava 7.0 primero.

Para finalizar, revisa las instrucciones de abajo para adaptar tu código.

Para migrar de OpenXava 7.4 a OpenXava 7.4.1

No hay consideraciones.

Para migrar de OpenXava 7.3.3 a OpenXava 7.4

Nueva fila en PDF generado en modo lista (para pruebas JUnit)

Ahora los PDF generados en modo lista tienen un nuevo elemento que muestra la cantidad de registros presentes en el reporte, por lo que si compruebas detalles del reporte en pruebas JUnit, es necesario hacer unos cambios, anteriormente era:

assertPopupPDFLinesCount(7);
assertPopupPDFLine(2, "Name");
Ahora es:
assertPopupPDFLinesCount(8); // +1
assertPopupPDFLine(2, "Record count: 3"); // SE AGREGÓ ESTA NUEVA FILA
assertPopupPDFLine(3, "Name");

Nueva acción en colecciones (para pruebas JUnit)

Ahora las colecciones tendrán una nueva acción tanto en lista como en cada fila, Collection.deleteSelected, por lo que si comprueban las acciones presentes en las pruebas JUnit, es necesario hacer algunos cambios, agregando la nueva acción y en algunos casos quitando Collection.removeSelected si la colección tiene (cascade=CascadeTYPE.REMOVE). Por ejemplo:

String [] actions = { 
"Collection.new", "Collection.edit",
"Collection.removeSelected", // QUITA ESTA ENTRADA SI LA COLECCIÓN TIENE ELIMINAR EN CASCADA "Collection.deleteSelected" // AÑADE ESTA ENTRADA }; assertActions(actions);
Lo mismo, si la colección tiene eliminar en cascada, debes cambiar la llamada de la acción por Collection.deleteSelected
public void testDeleteElementInCollection() throws Exception {
	....
	execute("Collection.removeSelected", "row=0,viewObject=xava_view_humans"); // QUITAR
	execute("Collection.deleteSelected", "row=0,viewObject=xava_view_humans"); // CAMBIAR POR
	...
}

Nueva acción en colecciones (para acciones personalizadas)

Collection.deleteSelected también afecta si tienes una colección con (cascade=CascadeType.REMOVE) y @RemoveSelectedAction personalizando la acción de Quitar.
En este caso deberás cambiar la anotación de @RemoveSelectedAction por @DeleteSelectedAction y el extends de la clase de la acción RemoveSelectedInCollectionAction por DeleteSelectedInCollectionAction.
Esto se debe que al tener eliminar en cascada, la acción Collection.removeSelected actúa de la misma forma que Collection.deleteSelected y por lo tanto el primero no aparecerá en la vista.

@OneToMany (mappedBy="delivery", cascade=CascadeType.REMOVE)
@RemoveSelectedAction(forViews="DEFAULT, MoreSections", value="DeliveryDetail.removeSelected") // QUITAR
@DeleteSelectedAction(forViews="DEFAULT, MoreSections", value="DeliveryDetail.deleteSelected") // CAMBIAR POR @DeleteSelectedAction,
// EL NOMBRE DE LA ACCIÓN EN EL CONTROLADOR NO ES OBLIGATORIO CAMBIARLO private Collection<Detail> details;
public class DeleteSelectedDeliveryDetailsAction 
	extends RemoveSelectedInCollectionAction { // QUITAR
	extends DeleteSelectedInCollectionAction { // CAMBIAR POR

Nueva acción en fila de colecciones (para pruebas JUnit)

Ahora cada fila de la colección tiene una nueva acción, CollectionOpenInNewTab.openInNewTab, por lo que si comprueban las acciones presentes en las pruebas JUnit, es necesario modificarlas y agregar la nueva acción. Por ejemplo:

String [] actions = { 
    "Collection.edit",
    "CollectionOpenInNewTab.openInNewTab" // AÑADE ESTA ENTRADA
};		
assertActions(actions);

Para migrar de OpenXava 7.3.2 a OpenXava 7.3.3

No hay consideraciones.

Para migrar de OpenXava 7.3.1 a OpenXava 7.3.2

No hay consideraciones.

Para migrar de OpenXava 7.3 a OpenXava 7.3.1

No hay consideraciones.

Para migrar de OpenXava 7.2.3 a OpenXava 7.3

Nuevas acciones en controlador Collection

Si no has sobrescrito el controlador Collection puedes saltear este paso. De lo contrario debes agregar manualmente las acciones previous y next en el controlador:

<action name="next"
	image="next.gif"
	icon="skip-next"
	class="org.openxava.actions.EditElementInCollectionAction">
	<set property="openDialog" value="false"/> 
	<set property="nextValue" value="1"/> 
</action>	
			
<action name="previous"
	image="previous.gif"
	icon="skip-previous"
	class="org.openxava.actions.EditElementInCollectionAction">
	<set property="openDialog" value="false"/> 
	<set property="nextValue" value="-1"/> 
</action>

Nuevas acciones en diálogos de colecciones (para pruebas JUnit)

Ahora los diálogos de las colecciones tienen dos nuevas acciones, Collection.previous y Collection.next, por lo que si comprueban todas las acciones presentes en las pruebas JUnit, hace falta modificarlas y agregar las nuevas acciones. Por ejemplo:

String [] bottomActions = { 
    "Collection.save",
    "Collection.hideDetail",
    "Collection.next", // AÑADE ESTA ENTRADA
    "Collection.previous" // AÑADE ESTA ENTRADA
};		
assertActions(bottomActions);

Ya no se soportan el uso de eval() en JavaScript

Si tienes tus propios editores o vistas personalizadas y estás utilizando tu propio código JavaScript, ten en cuenta que eval() ya no es compatible por razones de seguridad. Debes reescribir tu código JavaScript para no utilizar eval().

Si estás utilizando una biblioteca de terceros o si la cantidad de código que debes reescribir es considerable, y tu aplicación no requiere altos estándares de seguridad, puedes habilitar el soporte de eval() para tu aplicación OpenXava agregando la siguiente entrada a tu archivo xava.properties:

unsafeEvalInScripts=true

Para migrar de OpenXava 7.2.2 a OpenXava 7.2.3

No hay consideraciones.

Para migrar de OpenXava 7.2.1 a OpenXava 7.2.2

No hay consideraciones.

Para migrar de OpenXava 7.2 a OpenXava 7.2.1

No hay consideraciones.

Para migrar de OpenXava 7.1.6 a OpenXava 7.2

Ya no se soportan eventos en línea en editores y vistas personalizadas

Si tienes que escribir tus propios editores o vistas personalizadas y estás usando onclick, onfocus, onblur, etc., ya no van a funcionar. Tampoco funcionan los href="javascript: ". Esto es por razones de seguridad. Tienes que eliminar los eventos del HTML y moverlos a un archivo JS.

Es decir, si tienes un código como este en tu editor:

<a class="ox-card" 
    onclick="openxava.executeAction('<%=request.getParameter("application")%>', '<%=request.getParameter("module")%>', false, false, '<%=action%>', '<%="row=" + (i++)%>');">

Quita el evento onclick dejándolo de esta manera:

<a class="ox-card" data-action="<%=action%>" data-row="<%=i++%>">

Fíjate que hemos añadido atributos data- para guardas datos dinámicos que antes estaban en el JavaScript en línea, así podremos leer estos atributos desde nuestro código JavaScript después.

A continuación añade un archivo JS, digamos cardEditor.js (si el editor JSP se llama cardEditor.jsp), en src/main/webapp/xava/editors/js (crea la carpeta si todavía no existe) de tu proyecto, con el siguiente contenido:

openxava.addEditorInitFunction(function() {
	$('.ox-card').off('click').click(function() {
		openxava.executeAction(openxava.lastApplication, openxava.lastModule, false, false, 
			$(this).data('action'), "row=" + $(this).data('row'));
	});
});

Observa cómo utilizamos la clase, .ox-card en este caso, para añadir el evento usando código JavaScript. También usamos data() para obtener los valores de los atributos data que hemos guardado en el elemento HTML. Este código es seguro porque es descargado desde el servidor que aloja la aplicación.

Librerías JavaScript jQuery y jQuery UI actualizadas

jQuery se ha actualizado a la versión 3.7.1 desde la 1.11.2 y jQuery UI a la versión 1.13.2 desde la v1.11.2. Esta actualización se ha hecho por motivos de seguridad. Si únicamente usas la interfaz de usuario generada por OpenXava no tienes que hacer nada, sin embargo si tienes vistas personalizadas o editores propios y en estos usas jQuery deberías echas un vistazo a la guía de actualización para jQuery 3, puede que necesites hacer algún ajuste.

Incluir archivos JavaScript en JSP de editores o vista personalizada ya no funciona

Esto es por razones de seguridad. Normalmente los JS usados en editores propios o vistas personalizadas se incluyen en la carpeta xava/editors/js, cuando este es el caso no hay que hacer ningún cambio. Sin embargo, en algunas ocasiones el archivo JavaScript se ha incluido en el editor o la vista directamente, si este es el caso tenemos varias opciones.

La mejor alternativa es quitar el <script> del JSP y copiar tu archivo JS a la carpeta xava/editors/js.

Si esto no es posible, porque por ejemplo el JS es generado dinámicamente por un servlet, la solución es quitar el <script> del JSP y añadir un openxava.getString() en el archivo JS de tu editor. Por ejemplo, para el editor Discussion tenemos un discussion.js que está en xava/editors/js donde tenemos el código:

openxava.getScript(openxava.contextPath + "/dwr/interface/Discussion.js");

Si tu editor o vista personalizada aún no tiene un archivo JS, simplemente créalo y colócalo en xava/editors/js, sin importar que, por ahora, su única función sea cargar otro JS.

La última opción es mantener la etiqueta <script> en el JSP y agregarle un atributo de nonce. En otras palabras, si en el código JSP de tu editor o vista tienes algo como esto:

<script type='text/javascript' src='<%=contextPath%>/dwr/interface/Discussion.js?ox=<%=version%>'></script>

Lo deberías cambiar por:

<script type='text/javascript' <xava:nonce/> src='<%=contextPath%>/dwr/interface/Discussion.js?ox=<%=version%>'></script>

Fíjate en el <xava:nonce/> que hemos añadido. Aunque esta opción es la más rápida de implementar, las dos formas de JavaScript mencionadas anteriormente funcionan mejor.

Para migrar de OpenXava 7.1.5 a OpenXava 7.1.6

No hay consideraciones.

Para migrar de OpenXava 7.1.4 a OpenXava 7.1.5

No hay consideraciones.

Para migrar de OpenXava 7.1.3 a OpenXava 7.1.4

No hay consideraciones.

Para migrar de OpenXava 7.1.2 a OpenXava 7.1.3

HtmlUnit actualizado desde 2.70 a 3.3 (para pruebas JUnit)

Hemos tenido que actualizar a la última versión de HtmlUnit debido a una vulnerabilidad de seguridad crítica en las versiones 2.x. Si utilizas los métodos de ModuleTestBase en tus pruebas, no necesitas cambiar nada. Sin embargo, si utilizas la API de HtmlUnit directamente, usando getHtmlPage() o getWebClient() en tus pruebas, tendrás que realizar algunos ajustes de migración.

Sigue las instrucciones de la documentación de HtmlUnit para migrar de HtmlUnit 2.x.x a 3.x.x.

Para migrar de OpenXava 7.1.1 a OpenXava 7.1.2

No hay consideraciones.

Para migrar de OpenXava 7.1 a OpenXava 7.1.1

No hay consideraciones.

Para migrar de OpenXava 7.0.6 a OpenXava 7.1

Estilo en línea en HTML ya no está permitido.

Esto es por razones de seguridad. Esto significa que debes mover el estilo de HTML a CSS en tus vistas personalizadas, editores, formateadores, servlets, etc.

Por ejemplo, si tienes este código HTML:

<div style="padding: 20px; background-color: green;">

La parte de style ya no es reconocida. Ahora, debes cambiar el style por una class:

<div class="mi-fondo">

Y agregar la clase a tu archivo CSS (ya sea el CSS de tu tema o custom.css):

.mi-fondo {
    padding: 20px; 
    background-color: green;
}

También puedes cambiar el estilo por otras etiquetas HTML clásicas, como <b><i> o <font>. Especialmente cuando necesitas usar algún valor dinámico, como un color de una base de datos. Por ejemplo, podrías cambiar este código Java que genera HTML:

return "<i class='mdi mdi-square' style='color: " + valorHexColor + "'></i>";

Por esto:

return "<font color='" + valorHexColor + "'><i class='mdi mdi-square ox-color-inherit'></i></font>"; 

Fíjate en el uso de <font> para indicar el color. En este caso también utilizamos la clase ox-color-inherit (incluida en OpenXava) para sobrescribir el color dado por el CSS de OpenXava a los elementos <i>.

Los servlets requieren un tipo de contenido explícito.

Esto es por razones de seguridad. Tus servlets requieren establecer explícitamente el tipo de contenido. Por lo tanto, si todavía no lo hacías, debes agregar la siguiente línea a tus servlets:

response.setContentType("text/html"); 
Debes indicar el tipo MIME correspondiente, en este ejemplo "text/html" para un documento HTML.

JavaScript en línea en los JSP requiere el atributo nonce

Esto es por razones de seguridad. Rara vez se utiliza JavaScript en línea en el código de las aplicaciones de OpenXava, ya que no funcionan desde OpenXava 3.1 para editores o vistas personalizadas. Sin embargo, si tienes código personalizado fuera de un módulo OpenXava normal, como welcome.jsp, o algún encabezado o pie de página personalizado para tu aplicación, tal vez tengas algunos scripts en línea. En este caso, debes agregar un atributo nonce a tu script en línea utilizando la nueva etiqueta <xava:nonce/> de la biblioteca de etiquetas.

Por ejemplo, si tu página welcome.jsp tiene este código:

<script type="text/javascript"> 
    var button = document.getElementById('welcome_go_signin');
    button.onclick = function () { window.location='m/SignIn'; }
</script>

Deberías cambiarlo por:

<%@include file="../xava/imports.jsp"%>
    
    ...
    
<script type="text/javascript" <xava:nonce/>> 
    var button = document.getElementById('welcome_go_signin');
    button.onclick = function () { window.location='m/SignIn'; }
</script>

Fíjate en el nuevo elemento <xava:nonce> y que has de incluir imports.jsp.

Aún mejor, podrías buscar una alternativa que no use ningún script en línea. En este caso, por ejemplo, podríamos cambiar el evento onclick con un window.location por un simple <a ref="" />, si es posible.

Ya no se soportan eventos en línea en elementos HTML

Los eventos en línea todavía funcionan en los editores y vistas personalizadas en v7.1, sin embargo, si tienes código personalizado fuera de un módulo OpenXava normal, como welcome.jsp, tal vez tengas eventos en línea como onclick, onfocus, onblur, etc., que ya no van a funcionar. Esto es por razones de seguridad. Tienes que eliminar los eventos del HTML y moverlos a un archivo JS.

Es decir, si tienes un código como este:

<input type="button" tabindex="1" onclick="window.location='m/SignIn'" value="<xava:label key='SignIn'/>">

Quita el evento onclick y añade un id al elemento, dejándolo de esta manera:

<input id="welcome_go_signin" type="button" tabindex="1" value="<xava:label key='SignIn'/>">

Después añade un archivo JS, digamos eventos.js (o cualquier otro nombre que prefieras), en src/main/webapp/xava/editors/js (crea la carpeta si todavía no existe) de tu proyecto, con el siguiente contenido:

var button = document.getElementById('welcome_go_signin');
button.onclick = function () { window.location='m/SignIn'; }

Observa cómo utilizamos el ID para añadir el evento usando código JavaScript, un código seguro porque es descargado desde el servidor que aloja la aplicación.

IForwardAction ya no se puede utilizar para ejecutar JavaScript

Dadas las nuevas restricciones de seguridad, no es posible redirigir a JavaScript, por lo que si utilizas IForwardAction para redirigir a una URL que comienza con javascript: para ejecutar código, eso no funcionará. En su lugar, utiliza IJavaScriptPostAction para ejecutar JavaScript. Es decir, si tienes una acción como esta:

public class DecirHola extends BaseAction implements IForwardAction {    

    public void execute() throws Exception {
    }

    public String getForwardURI() {
    	return "javascript:alert('Hola')";
    }

    public boolean inNewWindow() {
        return false;
    }

}

Reescríbela de esta manera:

public class DecirHola extends BaseAction implements IJavaScriptPostAction {

    public void execute() throws Exception {
    }

    public String getPostJavaScript() {
	return "alert('Hola')";
    }

}

Las etiquetas en inglés ahora tienen otro orden (para las pruebas JUnit)

Notamos que las etiquetas en listas y colecciones, cuando están traducidas a inglés, si bien se entendían, podían estar mejor. Para esto, cambiamos el orden de las palabras y afecta al código JUnit que use métodos como assertValue(), assertLabelInList(), assertValueInCollection(), entre otros que se usen para verificar etiquetas. Por ejemplo, si tienes algo así:

assertLabelInList(0, "Year of invoice");

Cambiala por:

assertLabelInList(0, "Invoice year");

Si antes las etiquetas eran:

customer.address = Address of customer
customer.address.street = Street of address of customer
customer.address.street.number = Number of street of address of customer

Ahora son:

customer.address = Customer address
customer.address.street = Customer address street
customer.address.street.number = Customer address street number

Recargar página necesario para usar CSS en las pruebas (para pruebas JUnit)

Dado que el estilo en línea se ha movido a los archivos CSS ahora a veces es necesario que recargues la página para que el CSS funcione correctamente, por lo que si activas el CSS para tu prueba tienes que hacer un reload() después. Así:
getWebClient().getOptions().setCssEnabled(true); // Si haces esto...
reload(); // ...has de añadir esta línea
Curiosamente, el añadir el reload() no es necesario siempre, añádelo cuando te encuentres una prueba con CSS que falle.

Nueva acción en referencias y @DescriptionsList (para pruebas JUnit)

Las referencias y @DescriptionsList tienen una nueva acción para el usuario (Reference.clear), por lo que si comprueban todas las acciones presentes en las pruebas JUnit, hace falta modificarlas y agregar la nueva acción Reference.clear. Por ejemplo:
String [] acciones= {
	"CRUD.new",
	"CRUD.save",
	"CRUD.refresh",
	"Mode.list",
	"Reference.search",
	"Reference.createNew",
	"Reference.modify",
	"Reference.clear", // AÑADE ESTA ENTRADA
	"Sections.change"
};
assertActions(acciones);

Tomcat 8.x requiere nivel de compilación Java 8 como mínimo

Si usas Tomcat 8.x para tus aplicaciones en producción has de poner el nivel de compilación de las páginas JSP a 1.8 como mínimo. Para ello edita el archivo web.xml en la carpeta conf de tu Tomcat, busca un servlet llamado jsp y añade los siguiente parámetros:
<servlet>
	<servlet-name>jsp</servlet-name>
	<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
	...
	<!-- Añade los siguiente parametros para compilar con Java 8 -->
	<init-param>
	  <param-name>compilerSourceVM</param-name>
	  <param-value>1.8</param-value>
	</init-param>
	<init-param>
	  <param-name>compilerTargetVM</param-name>
	  <param-value>1.8</param-value>
	</init-param>		
	...
</servlet>

Nueva entidad a declarar en persistence.xml (para XavaPro)

Si usas XavaPro, o planeas usarlo en el futuro, edita el archivo persistence.xml y añade la siguiente entrada a todas tus unidades de persistencia
<class>com.openxava.naviox.model.SSORecord</class>

Añadir nuevo módulo SSO a rol admin y carpeta Admin (para XavaPro)

XavaPro incluye un nuevo módulo de administración llamado SSO. Al crear un nuevo proyecto este módulo está asociado por defecto al rol admin y está incluido en la carpeta Admin, sin embargo con los proyectos existente tienes que añadirlo tu manualmente, porque XavaPro no añade nuevos módulos a roles o carpetas automáticamente por seguridad.
Primero añade el módulo SSO al rol admin. Abre el módulo Roles, busca el rol admin en la lista y escógelo. Dentro del detalle de admin pulsa para añadir un nuevo módulo, busca SSO y añádelo:
Después añade el módulo SSO a la carpeta Admin. Abre el módulo Carpetas, busca la carpeta Admin en la lista y escógelo. Dentro del detalle de Admin pulsa para añadir un nuevo módulo, busca SSO y añádelo:

Para migrar de OpenXava 7.0.5 a OpenXava 7.0.6

@Column(length=x) sin scale ya no es scale=2 por defecto

Hemos arreglado un fallo relacionado con que scale=0 para @Column no funciona, y dado que cuando scale no está definido su valor por defecto es 0, ahora @Column(length=x) tiene scale=0 como valor por defecto en lugar de scale=2. Es decir, has de cambiar este código:

@Column(length=6)
BigDecimal factor;

Por este otro:

@Column(length=6, scale=2) // AÑADE scale=2
BigDecimal factor;

Si no defines length o precision el valor de scale todavía es 2, como siempre, por tanto si tienes:

@Column(column="FCTR")// scale es 2 por defecto, como siempre
BigDecimal factor;

No necesitas cambiar nada. Además, si la anotación @Column se omite por completo scale todavía es 2, como siempre.

Para migrar de OpenXava 7.0.4 a OpenXava 7.0.5

No hay consideraciones.

Para migrar de OpenXava 7.0.3 a OpenXava 7.0.4

No hay consideraciones.

Para migrar de OpenXava 7.0.2 a OpenXava 7.0.3

Los combos de @DescriptionsList en la parte del filtro de la lista ya no usan la clave

Para arreglar un fallo, los combos de las referencias marcadas como @DescriptionsList en el filtro de la lista o colecciones ya no usan la clave, sino el valor del campo. Esto es algo interno, no afecta el funcionamiento de la aplicación. Pero es posible que tengas que adaptar algo de código. Si tienes una condición como esta en una acción:

getTab().setConditionValue("vendedor.nombre", 1);

Cámbiala por:

getTab().setConditionValue("vendedor.nombre", "JUAN HERRERO");

Fíjate como ahora para vendedor.nombre usamos el nombre del vendedor, no el id. Hemos hecho esto para arreglar un bug, pero como efecto secundario ahora es más natural y además funciona de la misma manera para referencias con o sin @DescriptionsList, así que añadir o quitar un @DescriptionsList a una referencia no afecta al código de tus acciones.

También tienes que adaptar tu código JUnit que pone valor al filtro de la lista si se usan referencias con @DescriptionsList. Es decir,  cambia:

setConditionValues("", "1");
Por:
setConditionValues("", "AUTOMÓVIL");

Aquí estás cambiando el id por la descripción o el nombre. Haz lo mismo con el código JUnit que verifica el contenido del combo. Cambia:

String [][] valoresValidos = {
    { "", "" },
    { "2:_:FAROLA", "FAROLA" },
    { "0:_:CASA", "CASA" },
    { "3:_:PUERTA", "PUERTA" },
    { "1:_:AUTOMÓVIL", "AUTOMÓVIL" }
};
assertValidValues("conditionValue___3", valoresValidos);        

Por:

String [][] valoresValidos = {
    { "", "" },
    { "FAROLA", "FAROLA" },
    { "CASA", "CASA" },
    { "PUERTA", "PUERTA" },
    { "AUTOMÓVIL", "AUTOMÓVIL" }
};
assertValidValues("conditionValue___3", valoresValidos);

Nota como hemos quitado el prefijo id:_: en la parte de la clave del mapa. Ahora, las claves y los valores son iguales.

Para migrar de OpenXava 7.0.1 a OpenXava 7.0.2

No hay consideraciones.

Para migrar de OpenXava 7.0 a OpenXava 7.0.1

No hay consideraciones.

Para migrar de OpenXava 6.6.3 a OpenXava 7.0

Convertir tu proyecto a estructura Maven

OpenXava 7 es compatible con Maven, por lo que la estructura clásica de un proyecto OpenXava ya no se reconoce. Has de convertir tu proyecto en un proyecto estándar de Maven. Por suerte, todo tu código actual es válido, sólo que tiene que estar colocado en carpetas diferentes. Si no estás familiarizado con Maven, mira la disposición estándar de directorios en un proyecto Maven.

La forma más fácil de migrar a Maven es crear un nuevo proyecto usando OpenXava 7.0 y después copiar el código fuente y los recursos desde tu proyecto actual al nuevo. Es decir, lo primero es crear un nuevo proyecto OpenXava usando Openxava Studio 7, para ello sigue las instrucciones de la guía de primeros pasos.

El siguiente paso es copiar todo el código fuente y los recursos desde el viejo proyecto a la carpeta correspondiente en el nuevo proyecto, como sigue:

El código de pruebas está en una carpeta diferente en Maven, por lo que deberías copiar:

Lo de arriba es suficiente para la mayoría de las aplicaciones.

El código web ahora está en src/main/webapp en lugar de web. Primero, crea una carpeta llamada xava en src/main/webapp para poner ahí tu código web.
Si tienes tu propios editores personalizados copia el código de los editores:

Copia también:

Los archivos servlets.xml, filters.xml y listeners.xml ya no se soportan. Puedes copiar su contenido a web.xml, que ahora está vacío y listo para tus propias cosas, en src/main/webapp/WEB-INF. Si usas las anotaciones @WebServlet, @WebFilter y @WebListener no tienes que hacer ningún cambio.

Si usas una librería de terceros extra en tu aplicación has de añadir una dependencia en el archivo pom.xml en la raíz de tu proyecto. Ya no vas a copiar jars en web/WEB/lib. Si no estás familiarizado con Maven lee sobre el mecanismo de depencia de Maven.

Si usas una base de datos que no sea HSQLDB has de añadir la dependencía para tu controlador JDBC. Por ejemplo, si usas MySQL añade la siguiente entrada a tu pom.xml:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.29</version>
</dependency>

Para otra base de datos simplemente pregunta a Google, algo como "maven dependency oracle" por ejemplo. Para que tu controlador JDBC se descargue y se incluya en tu proyecto has de ejecutar "mvn package" en tu proyecto. Puedes hacerlo desde la línea de órdenes (si tienes Maven instalado en tu máquina) o desde OpenXava Studio (no es necesario tener Maven instalado), con Run As > Maven Build... en tu proyecto y tecleando "package" como goal. Este paso no es necesario si usas HSQLDB como base de datos.

Ahora puede ejecutar tu aplicación. Pon tu ratón en src/main/java de to proyecto y escoge Run As > Java Application. A partir de ahora, puedes modificar tu código y relanzar tu aplicación como siempre, incluso si la lanzas en modo de depuración puedes modificar el código y ver el resultado sin relanzar la aplicación. Es decir, puedes trabajar en desarrollo como lo has hecho siempre.

Ya no usamos Ant. Ahora lo vas a hacer todo usando comandos de Maven. Si no conoces Maven muy bien lee alguna documentación de introducción a Maven. Por ejemplo, para crear el war para desplegar en producción usaras "mvn package", y obtendrás el war listo para ser desplegado en Tomcat en la carpeta target de tu proyecto.  Puedes ejecutar todos los comandos Maven desde dentro de OpenXava Studio, con la opción Run As en tu proyecto.

Fíjate que cuando creas el proyecto con OpenXava el nombre del proyecto está en minúsculas, esto es porque la nomenclatura para Maven es usar minúsculas para el nombre del artifactId, que coincide con el nombre del proyecto y el archivo a generar (el war). Para proyectos nuevo deberías usar minúsculas para tu nombre de proyecto. Sin embargo, por años hemos promovido el usar mayúscula para la primera letra del nombre del proyecto en la documentación, por lo que probablemente tengas tu viejo proyecto con el nombre empezando por mayúscula. Puedes elegir migrar a minúsculas y adoptar el estándar Maven, pero ten en cuenta que esto cambiaría la URL que usan tus usuarios.
Es decir, si el nombre de tu aplicación era "Almacenes" y lo cambias a "almacenes", ahora la siguiente URL: https://tusitio.com/Almacenes ya no va a funcionar. Ahora has de usar https://yoursite.com/almacenes (con almacenes en minúsculas). Si esto es aceptable para tus usuarios, perfecto. Si no, puedes renombrar tu proyecto Maven para que use el viejo nombre (Almacenes en este caso) y tus usuarios pueden continuar usando las URLs originales.
Digamos que quieres cambiar el nombre de proyecto de "almacenes" a "Almacenes". Para ello edita pom.xml y cambia:
<artifactId>almacenes</artifactId>
Por:
<artifactId>Almacenes</artifactId>
También en pom.xml cambia:
<finalName>almacenes</finalName>
Por:
<finalName>Almacenes</finalName>
Después edita aplicacion.xml (en src/main/resources/xava) y cambia:
<aplicacion nombre="almacenes">
Por:
<aplicacion nombre="Almacenes">
También en la clase lanzadora, es decir almacenes.java en el paquete com.tuempresa.almacenes.run, cambia:
AppServer.run("almacenes");
Por:
AppServer.run("Almacenes");
Para finalizar, deberías hacer en tu proyecto un Run As > Maven clean (mvn clean) y después Run As > Maven Build... tecleando package como goal (mvn package).

Hibernate actualizado desde 5.3 a 5.6

Hemos trabajado duro adaptando OpenXava para que funcione bien con Hibernate 5.6. Sin embargo, puedes encontrar problemas en tu propio código JPA/Hibernate. Si usas la API de JPA todo debería funcionar tal cual, pero hay nuevos bug en Hibernate 5.6 que pueden hacer que tu código falle. Hemos encontrado algunos.

Join requerido en referencias en clave

Con Hibernate 5.3 cuando usas una propiedad de una referencia y esta es parte de la clave, no necesitas añadir un join explicito en la consulta. Esto es de esta forma no importa el nivel de profundidad. En Hibernate 5.6, no necesitas añadir un join si tienes sólo un nivel de referencia, pero si tienes un segundo nivel, has de añadirlo, si el segundo nivel tiene una clave compuesta.

Diciéndolo con código. Si tienes:

@Entity
public class CargoTransporte {
	
    @Id @ManyToOne
    private Albaran albaran;

    ...
	
}

@Entity
public class Albaran {
	
    @Id 
    private int numero;

    @Id @ManyToOne
    private Factura factura;

    ...
	
}

@Entity
public class Factura {
	
    @Id 
    private int anyo;
	
    @Id 
    private int numero;

    ...
	
}

Con el código de arriba la siguiente consulta funciona bien con Hibernate 5.3:

String consulta="from CargoTransporte c where c.albaran.factura.anyo = :albaran_factura_anyo";
Query query = XPersistence.getManager().createQuery(consulta);
query.setParameter("albaran_factura_anyo", 2022);

Pero falla con Hibernate 5.6. Curiosamente si ejecutas la consulta contra Albaran preguntando por factura.anyo funciona, sólo falla con 2 niveles o más. Además, si Factura hubiera tendido clave simple, en lugar de compuesta, hubiera funcionado también. Hibernate 5.6 falla cuando combinas más de un nivel con claves compuestas.

No te preocupes, la solución es sencilla, simplemente añade un join explicito para la primera referencia. Es decir, de la siguiente forma funciona con Hibernate 5.6:

String consulta="from CargoTransporte c join fetch c.albaran a where a.factura.anyo = :albaran_factura_anyo";
Query query = XPersistence.getManager().createQuery(consulta);
query.setParameter("albaran_factura_anyo", 2022);

La solución es el join fetch c.albaran a. Moraleja, si alguna consulta te falla con Hibernate 5.6 prueba añadir un join explicito para tu referencia.

Esquema no creado automáticamente

Un nuevo bug en Hibernate 5.6 es que ya no reconoce javax.persistence.create-database-schemas, por lo que si tienes la siguiente configuración en tu persistence.xml:

<persistence-unit name="default">
    ...
    <properties>
        <property name="javax.persistence.schema-generation.database.action" value="update"/>
        <property name="javax.persistence.create-database-schemas" value="true"/> 
        <property name="hibernate.default_schema" value="MIESQUEMA"/>
    </properties>
</persistence-unit>

Con Hibernate 5.3 crea el esquema MIESQUEMA y después las tablas dentro, sin embargo con Hibernate 5.6 el esquema MIESQUEMA no se crea, por ende las tablas tampoco se crean. La solución es crear el esquema MIESQUEMA a mano. Has de contectarte a tu base de datos con tu explorador de base de datos y ejecutar una sentencia CREATE SCHEMA MYSCHEMA (o equivalente). Después, puedes arrancar tu aplicación y las tablas serán creadas.

Clase de utilidad XHibernate quitada

La clase de utilidad XHibernate se ha quitado porque se usaba en las aplicaciones con componentes XML, en las aplicaciones JPA usamos XPersistence en su lugar, y hemos quitado el soporte para componentes XML en v7.0. El API de Hibernate todavía está disponible. En el raro caso de que uses XHibernate en algún punto de tu código, cambia:

Session session = XHibernate.getSession();
session.save(factura);

Por:

Session session = (Session) XPersistence.getManager().getDelegate();
session.save(factura);
Es decir, puedes obtener un objeto Session de Hibernate desde el manager de JPA. Otra alternativa sería obtener la sesión de Hibernate directamente a la manera de Hibernate, aunque en este caso has de encargarte tú de crear la SessionFactory y ser responsable de cerrar la transacción y la sesión.

Recursos del proyecto en lugar diferente (para las pruebas JUnit)

Dado que ahora tus proyectos OpenXava tienen un estructura Maven estándar, la mayoría de los recursos de tu proyecto están en un lugar diferente ahora, por lo que si los usas en alguna de tus pruebas JUnit has de adaptar la ruta del recurso.
Por ejemplo, si tienes la siguiente línea en tu prueba JUnit:
uploadFile("scripts", "informes/Corporacion.html");
Deberías cambiarlo por:
uploadFile("scripts", "src/main/resources/informes/Corporacion.html");
Fíjate como cambiamos  informes por src/main/resources/informes en la ruta, porque ahora todos los recursos están en src/main/resources.

HtmlUnit actualizado de 2.32 a 2.63 (para las pruebas JUnit)

Si usas para las pruebas los métodos de ModuleTestBase no necesitas tocar nada. Sin embargo, si usas directamente el API de HtmlUnit, algo que puede ocurrir si usas getWebClient() o getHtmlPage() en tu prueba, en ese caso puede ser que necesites adaptar tu código. HtmlUnit mantiene viva su tradición de añadir cambios que producen incompatibilidad hacía atrás en cada versión menor, para ello cambian caprichosamente el nombre de los métodos, mueven las cosas de un paquete a otro o cambian el comportamiento de algún método. Hemos encontrado la siguientes cosas, por ejemplo.
El método asText() de HtmlElement ha sido renombrado como asNormalizedText(), por lo que si tienes un código como este en tu prueba:
HtmlElement tarjeta = body.getElementsByAttribute("div", "class", "ox-card").get(2);
assertEquals("Precio unitario: 0.00, Precio unitario en pesetas: 0"), tarjeta.asText());
Cámbialo por:
HtmlElement tarjeta = body.getElementsByAttribute("div", "class", "ox-card").get(2);
assertEquals("Precio unitario: 0.00, Precio unitario en pesetas: 0"), tarjeta.asNormalizedText());
Por si fuera poco asNormalizedText() no funciona exactamente igual que el antiguo asText(), ahora cambia cada salto de línea por un único \n. Esto significa que quizás tengas que cambiar algo en el código de prueba si usas asText() y examinas los saltos de línea. Por ejemplo, si tienes el siguiente código de prueba:
assertDiscussionCommentText("discusion", 0, Strings.multiline("admin - Ahora", "Hola, soy yo")); 
Cámbialo por:
assertDiscussionCommentText("discusion", 0, "admin - Ahora\nHola, soy yo");
Fíjate que ya no usamos la utilidad Strings.multiline() y usamos un único \n. En este caso no hemos usado asNormalizedText() directamente, sino assertDiscussionCommentText() de ModuleTestBase que usa asNormalizedText() para su implementación. Es decir, algunos métodos de ModuleTestBase están afectados por el nuevo comportamiento, entre ellos assertValueInList() del formato tarjetas de la lista, ahora has de usar un único \n en lugar de \r\n. Por lo que has de cambiar:
assertValueInList(2, "XAVA\r\n3\r\nPrecio unitario: 0");
Por:
assertValueInList(2, "XAVA\n3\nPrecio unitario: 0");
Otro cambio en la forma en que HtmlUnit funciona es que usa caracteres UNICODE en lugar de ANSI, por lo que si verificas caracteres especiales has de adaptar tu código. Por ejemplo, deberías cambiar:
assertEquals(
    "javascript:openxava.executeAction('openxavatest', 'Carrier', 'Effacer l" 
        + (char) 145 // ANSI  
        +"entité courante: Etes-vous sûr(e) ?', false, 'CRUD.delete')", 
    deleteLink.getHrefAttribute());
Por:
assertEquals(
    "javascript:openxava.executeAction('openxavatest', 'Carrier', 'Effacer l" 
        + (char) 8216 // UNICODE
        +"entité courante: Etes-vous sûr(e) ?', false, 'CRUD.delete')", 
    deleteLink.getHrefAttribute());
Fíjate que hemos cambiado 145 por 8216. Mira en esta tabla para saber el mapeo entre ANSI y UNICODE.
Ahora en las propiedades de tipo @HtmlText o @Stereotype("TEXTO_HTML") obtienes el contenido real, incluyendo las etiquetas de HTML, seguramente por causa de un mejor soporte de JavaScript en HtmlUnit. Por lo tanto, si tienes una propiedad @HtmlText llamada descripcion, cambia:
assertValue("descripcion", "Esto es una gran discusión sobre jUnit");
Por:
assertValue("descripcion", "<p>Esto es una gran discusión sobre jUnit</p>");
También, getValue() y assertValue() ahora hacen un trim() para funcionar mejor con el nuevo comportamiento de HtmlUnit, por lo que has de cambiar:
assertValue("poblacion", "46540 ");
Por:
assertValue("poblacion", "46540");
Fíjate como hemos quitado el espacio después de 46540.
El nuevo HtmlUnit requiere que recargues la página para que el CSS funcione correctamente, por lo que si activas el CSS para tu prueba tienes que hacer un reload() después. Así:
getWebClient().getOptions().setCssEnabled(true); // Si haces esto...
reload(); // ...has de añadir esta línea
Curiosamente, el añadir el reload() no es necesario siempre, añádelo cuando te encuentres una prueba con CSS que falle.

Apache POI actualizado de 3.15 a 5.1

Apache POI es una librería Java usada para manipular documentos de Microsoft, como Excel. JasperReports la usa por eso ha sido necesario actualizar POI para que la última versión de JasperRerpots funcione. Si no usas POI directamente no tienes que hacer nada. Sin embargo, si usas la API de POI en tu código, has de adaptarla, porque ellos han refactorizado todo el código cambiando nombres y lugares, para hacerlo incompatible. Estos son algunos de los cambios de los que nos hemos dado cuenta.
Han convertido todas las variables finales en enums, estos son algunos ejemplos:
CellType.NUMERIC // En lugar de Cell.CELL_TYPE_NUMERIC
HyperlinkType.FILE // En lugar de Hyperlink.LINK_URL
FillPatternType.SOLID_FOREGROUND // En lugar de CellStyle.SOLID_FOREGROUND
HSSFColor.HSSFColorPredefined.RED // En lugar de HSSFColor.RED
BorderStyle.THIN // En lugar de CellStyle.BORDER_THIN
HorizontalAlignment.LEFT // En lugar de CellStyle.ALIGN_LEFT
Si necesitas usar los valores short de las viejas variables finales puedes usar los métodos getCode() y valueOf() presentes en la mayoría de los nuevos enums.
El método setCellType() de Cell se ha eliminado:
Cell cell ... 
// cell.setCellType(Cell.CELL_TYPE_FORMULA); // Ya no existe, no es necesario
cell.setCellFormula(text);
setCellType() ya no es necesario porque Cell colige el tipo del valor de la celda.
El método setBoldweight() de Font se ha eliminado. Por lo que tienes que cambiar esto:
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
Por:
font.setBold(true);
Fíjate en el nuevo método setBold() en Font.
Hay más cambios incompatibles en la nueva versión de Apache POI. No te preocupes, el compilador te avisará de ellos y StackOverflow te ayudará a arreglarlos.

Para migrar a OpenXava 6.6.3

Para migrar a OpenXava 6.6.3 desce cualquier versión anterior de OpenXava, incluso desde la 1.0:

Sigue las instrucciones de migración para OpenXava 6.x