Java - Problema serialización (nivel novato)

 
Vista:
sin imagen de perfil

Problema serialización (nivel novato)

Publicado por Murph (4 intervenciones) el 02/04/2021 11:42:27
Hola!

Tengo un proyecto que es una práctica de clase.Es muy muy sencillo, es un simple formulario de alta y baja de vehículos. El caso es que tengo que guardar toda la lista actual en un archivo .dat pero cada vez que lo hago, me da un error al serializar por un tema relacionado con las fechas o el Calendar:

java.io.NotSerializableException: com.toedter.calendar.DateUtil

Proyecto: https://we.tl/t-zvNj1QzAra

Para probarlo simplemente agregas un alta nuevo (Autos > Alta), y luego en cuando está agregado pulsamos en "Opciones > Salir" (aquí es donde guarda y da error).

Si alguien me puede ayudar sería de agradecer.
Saludos.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Problema serialización (nivel novato)

Publicado por Kabuto (1382 intervenciones) el 02/04/2021 12:28:13
Creo que el problema se debe a que estás usando una librería no oficial de Java que probablemente no implementa serializable

1
java.io.NotSerializableException: com.toedter.calendar.DateUtil

Esa librería de Toedter para el selector de fecha, la empleas en varias clases de la Vista:

imagen_2021-04-02_120954


Aunque en realidad la pregunta es: ¿Por qué estarías serializando también elementos de la Vista, cuando supongo que lo único que quieres guardar es el listado de autos?

Cuando serializas la clase ListaAutos, que es la que entiendo quieres guardar, resulta que también estás serializando la clase Control, porque es un atributo de ListaAutos.
Y tu guardas el objeto ListaAutos al completo:
1
salida.writeObject(this);

Y eso incluye todos sus atributos, también al objeto Control
1
2
3
4
5
public class ListaAutos implements Serializable {
 
    private ArrayList<Auto> lista;
    private static int totalAuto;
    private Control ctrl;

La clase Control, tiene como atributos las clases "dialogo" de la Vista, que son las que usan la librería no oficial.
Y todo eso, lo estás intentando serializar también:
1
2
3
4
5
6
7
8
9
10
11
public class Control implements Serializable{
 
    FrmPrincipal frmPpal;
    DlgAutoAlta dlgAutoAlta;
    DlgAutoListado dlgAutoList;
    DlgAutoBaja dlgAutoBaja;
    DlgAutoModificaciones dlgAutoMod;
    DlgAutoStats dlgAutoStats;
    ListaAutos lista;
 
    Boolean hayCambios;

Esto supone serializar demasiadas cosas que no son necesarias guardar en disco. Y lo peor es que algunas de esas cosas, no son serializables, como ocurre con las clases de com.toedter

Tendrías que reinterpretar el código de manera que la clase Control quede separada de ListaAutos, quizás creando una clase intermedia.

Esto es como lo tienes ahora:
1
2
3
4
5
public class ListaAutos implements Serializable {
 
    private ArrayList<Auto> lista;
    private static int totalAuto;
    private Control ctrl;

Puedes intentar que ListaAutos se quede solo con el ArrayList, el int estatico y los métodos que sean necesarios para gestionar la lista: buscarAuto, borrarAuto, etc....

Y entonces crear una nueva clase, que se llame por ejemplo GestionLista o algo así... y que sus atributos sean ListaAutos y Control.
No tiene por qué implementar Serializable.

1
2
3
4
public class GestionLista {
 
    private ListaAutos listaAutos;
    private Control ctrl;

Y esta clase tendría los métodos para guardar en disco y para setear el Controlador.

Y cuando escriba en disco, NO se escribirá así misma:
1
salida.writeObject(this);

Lo que ha de escribir, será únicamente el atributo listaAutos
1
salida.writeObject(listaAutos);

De esta manera evitas serializar a Control, y con ella a todas sus dependencias.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Problema serialización (nivel novato)

Publicado por Murph (4 intervenciones) el 02/04/2021 12:58:37
Hola.

Antes que nada gracias por todo lo que me has dicho. Mi nivel es bastante básico porque no controlo mucho y lo que he hecho es directamente cambiar el this por lista (que es la lista completa de los automóviles).

El problema es ahora que retorna:
Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList cannot be cast to autos.modelo.ListaAutos
at autos.modelo.ListaAutos.cargarLista(ListaAutos.java:118)
at Autos.main(Autos.java:39)

Es en el proceso de carga, voy a ver si doy con el problema.
Gracias de nuevo!!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Problema serialización (nivel novato)

Publicado por Kabuto (1382 intervenciones) el 02/04/2021 21:34:40
Se debe a que hora estás guardando simplemente el ArrayList.
Eso puede ser más que suficiente para lo que necesitas.

Pero, cuando vas a recuperar de disco, si no has cambiado este método, al leerlo lo estás intentando convertir en la clase ListaAutos

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public ListaAutos cargarLista(String ruta) {
 
    FileInputStream fis = null;
    ObjectInputStream entrada = null;
 
    ListaAutos lista = null;
    try {
        File fichero = new File(ruta);
        if (fichero.exists()) {
            fis = new FileInputStream(ruta);
            entrada = new ObjectInputStream(fis);
            lista = (ListaAutos) entrada.readObject();
        } else {
            lista = new ListaAutos();
        }
 
    } catch (IOException ex) {
        System.out.println("Fallo la carga del archivo 1-> " + ex.getMessage());
 
    } catch (ClassNotFoundException ex) {
        System.out.println("Fallo la carga del archivo 2-> " + ex.getMessage());
    }
 
    return lista;
}

Tienes que cambiarlo para que lo lea como ArrayList<Auto>

Prueba con algo como esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public ArrayList<Auto> cargarLista(String ruta) {
 
    FileInputStream fis = null;
    ObjectInputStream entrada = null;
 
    ArrayList<Auto> lista = null;
    try {
        File fichero = new File(ruta);
        if (fichero.exists()) {
            fis = new FileInputStream(ruta);
            entrada = new ObjectInputStream(fis);
            lista = (ArrayList<Auto>) entrada.readObject();
        } else {
            lista = new ArrayList<Auto>();
        }
 
    } catch (IOException ex) {
        System.out.println("Fallo la carga del archivo 1-> " + ex.getMessage());
 
    } catch (ClassNotFoundException ex) {
        System.out.println("Fallo la carga del archivo 2-> " + ex.getMessage());
    }
 
    return lista;
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Problema serialización (nivel novato)

Publicado por Murph (4 intervenciones) el 02/04/2021 22:08:21
Emmmmmmm no sé qué vas a pensar de mí pero bueno jajajaja
Ahora no sé cómo llamar al método cargar lista porque yo en el controlador hacía lo siguiente:

1
2
3
String ruta = "ListaAutos.dat";
ListaAutos lista;
lista = lista.cargarLista(ruta);

El tema es que estoy llamando al método pero me dice que no puede convertirlo a ListaAutos (obviamente).
No estás en deuda conmigo, si me puedes ayudar bien y si no no te preocupes, millones de gracias por tu tiempo.

Saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Problema serialización (nivel novato)

Publicado por Kabuto (1382 intervenciones) el 03/04/2021 01:48:46
Ey, no desesperes.

Vale, el controlador cuando pide cargar lista, espera recibir una referencia a ListaAutos.
Bien, pues cambiemos de nuevo el método para que recupere el objeto ArrayList serializado en disco y por último devuelva la referencia a ListaAutos.

Además, me acabo de dar cuenta, de que al carga el ArrayList, se está asignando a un ArrayList "nuevo" que se crea dentro de ese método, no se está asignando al atributo de ListaAutos.
Se llaman igual , "lista", pero son ArrayList diferentes porque están en "ámbitos" distintos.

Esto también lo debemos cambiar, y creo que basta con eliminar la línea que dejo como comentario.

Marco en negrita lo que cambia

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public ListaAutos cargarLista(String ruta) {
 
    FileInputStream fis = null;
    ObjectInputStream entrada = null;
 
    //ArrayList<Auto> lista = null;//Eliminar esta línea
    try {
        File fichero = new File(ruta);
        if (fichero.exists()) {
            fis = new FileInputStream(ruta);
            entrada = new ObjectInputStream(fis);
            lista = (ArrayList<Auto>) entrada.readObject();
        } else {
            lista = new ArrayList<Auto>();
        }
 
    } catch (IOException ex) {
        System.out.println("Fallo la carga del archivo 1-> " + ex.getMessage());
 
    } catch (ClassNotFoundException ex) {
        System.out.println("Fallo la carga del archivo 2-> " + ex.getMessage());
    }
 
    return this; //Controlador recibe referencia a ESTE objeto ListaAutos
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil

Problema serialización (nivel novato)

Publicado por Murph (4 intervenciones) el 03/04/2021 08:11:48
Hola!

Eres un crack, y no solo eso, si no que además he aprendido y entendido todo lo que me has explicado... Funciona correctamente, millones de gracias.

Un abrazo!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar