style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Como retornar una lista desde un web service o desde un RMI (Spring Remoto)

Buenas tardes compañeros de la comunidad.

Mi pregunta es para saber si existe la forma de retornar una lista desde un web service.

Lo que pasa es que estoy tratando de migrar algunos módulos de un sistema a un web service; y no puedo cambiar la estructura del sistema, por lo que lo que tengo que hacer es que se adecue al sistema.

Quería retornar una lista de tipo:

List listaRetorno = new LinkedList();

En el que hay varios tipos de datos como un arreglo bidimensional, una cadena, un boleano, y un entero (en la lista de retorno).
al tratar de retornarlo desde el web service me arroja errores tipo : java.rmi.UnmarshalException

y por lo mismo me vi en la necesidad de retornar la lista desde una aplicacion con RMI de Spring Remoto, y tampoco funciona, el error es el mismo.

Alguna sugerencia???

Gracias.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

Re: retornar una lista

no puedo cambiar la estructura del sistema

    ▲ ¿A qué te refieres exactamente?

Imagen de adrianaaae

A que tengo que devolver la lista

A que debo de devolver en la lista los datos que comente anteriormente en una sola conexión al WS, y en el LinkedList.
de modo que en una sola petición al WS necesito retornar una lista donde se encuentran un arreglo bidimensional, una cadena, un booleano y una arreglo normal (unidimensional).

Y la forma en que se debería de retorna es en el tipo de lista LinkedList.

Gracias!!!

Re: debo de devolver

 

¿Necesariamente tiene que ser una lista? Si tú codificas la implementación del servicio (service implementation class), ¿acaso no podrías generar el cliente?

JAX-WS utiliza JAX-B para serializar/deserializar las peticiones/respuestas. Que una operación (@WebMethod) devuelva una lista no está soportado directamente, aunque un bean con una lista de un tipo concreto como miembro.

Imagen de adrianaaae

Gracias por tu respuesta

Si tiene que ser una lista, ya estoy haciendo la implementación del web service desde un cliente, pero al momento de querer devolver la lista salta un error que era el que comentaba anteriormente, y pues el problema con lo que dices de serializar es que este modulo no usa clases y objectos, sino devuelve los datos para realizar un catálogo; es por eso que tiene que ser de ese modo.

Esto es lo que debería de devolver la lista (contenido dinámico):

- Object[][] modelTable -->es un array bidimensional donde se contiene la tabla a consultar.
- String[] encabezado = new String[n] --> es un arreglo simple
- Un boleano (se usa como badera, pero a fuerza tengo que regresarlo en la lista)
- Un mensaje de tipo String

Y pues no usa objectos (por eso no puede generar un bean) y pues si te preguntas por que no lo hago de otro modo, es por que utiliza un framework y eso obliga a hacerlo así.

Gracias.

Imagen de pechsclk

Lo retornas asi

Si retornas un list en cliente debe aceptar un list

List listaRetorno = new LinkedList();

en lo personal estoy programando una aplicacion en RMI y hago los retornos de JTableModel, ArrayList, JComboBoxModel y trabajo bien

por ejemplo quiero retornar un ArrayList lo tengo de la siguiente manera

interfas de la aplicacion esta de esta manera

public ArrayList<string> datos_de_list_clientes(String clave) throws RemoteException;

en donde se impleta esta de este modo

public ArrayList<string> datos_de_list_clientes(String clave) throws RemoteException{
ArrayList<string> datos = new ArrayList<>();
try{
sql= la consulta a la base de datos;
resulset;
while(rs.next()){
// aqui en el for depende cuantos registros quiero mostrar
for(int i = 1; i <= 9; i++){
datos.add(rs.getString(i))
}
}
}catch(Exception e){
System.out.println(e);
}
return datos;
}

el cliente lo resive de esta forma

public void resive_datos(String clave_cliente){
try{
 ArrayList<string> datos = new ArrayList<>();
datos = objRemoto.datos_de_list_clientes(clave_cliente);
//ahora si quiero ver el contenido del retorno hago esto
int tam = datos.size();
for (int i = 0; i < tam;i++){
system.out.println(datos.get(i));
}
}catch(Exception e){
System.out.println(e);
}
}
Imagen de adrianaaae

RMI

Bueno de hecho al ver que con el web service no lo podía retornar (la lista) traté de retornarlo con el RMI de Spring Remote, pero me marca el mismo error, y pues estoy tratando de retornar dentro de la lista también un JTableModel pero me marcaba error: java.rmi.UnmarshalException

Y me pedía que lo serialice y lo hice pero tampoco me funcionó.

Y la forma como lo hiciste es con RMI nativa de java (son Spring ni nada)???

Lo preguntaba por que si es con Spring se necesita configurar un archivo y me podría servir para verificar si lo estoy heciendo bién.

Gracias por tu respuesta.

Imagen de pechsclk

pon tu codigo

Aver pon tu codigo.. como lo haces.
a lo mejor asi se puede checar donde esta el error, a lo mejor es algo pequeño..

Capa de abstracción

 

Si tienes un sistema heredado y quieres integrarlo con otros sistemas, necesitas construir una capa de abstracción (en rojo en la siguiente imagen) para exponerlo como un servicio web:

Sistema

No es necesario que esta capa de abstracción esté construida en el mismo lenguaje. Algo similar hacen los Enterprise Service Bus (ESB): exponen tal sistema heredado como un servicio.


P.D. En mi opinión, en estos días, RMI es una solución para salir del paso.

~~~

Imagen de adrianaaae

Ok gracias

lo siento pero no puedo pegar código aqui, por que es de la empresa donde trabajo.

Solo puedo decir que estoy tratando de retornal lo que mencionaba anteriormente.

Pero aquí pongo el pseudocódigo.

Existe un método:

public List getDetalles(parámetros){
List lst= new LinkedList();
String[] encabezado;
Object[][] modeloInterno;
String mensaje;
boolean bandera;

...
.......
.........

despúes de un procedimiento
en el web service ...

lst.add(encabezado);
lst.add(modeloInterno);
lst.add(mensaje);
lst.add(bandera);

return lst;

}

Pero cuando quiere devolver el pojo o resultado el web service truena y me carca el error
que había mencionado anteriormente donde me indica que no se pudo generar el XML del
return; es decir que no logra devolver nada.

-------------------------------------------------------
Gracias por su ayuda.

Imagen de pechsclk

pon el codigo

aver porque no pones el codigo completo donde quieres retornar el modelo de la tabla

Imagen de adrianaaae

Modelo

Este es el modelo de la tabla:

                    tmodel = new DefaultTableModel(modelCond, columnNames) {
                        Class[] types = new Class[]{
                            java.lang.String.class, java.lang.String.class,
                            java.lang.Float.class, java.lang.String.class,
                            java.lang.Integer.class, java.lang.String.class,
                            java.lang.Float.class, java.lang.String.class,
                            java.lang.String.class, java.lang.Integer.class,
                            java.lang.String.class, java.lang.Boolean.class,};
                        boolean[] canEdit = new boolean[]{
                            false, false, false, false, false, false,
                            false, false, false, false, false, false
                        };

                        @Override
                        public Class getColumnClass(int columnIndex) {
                            return types[columnIndex];
                        }

                        @Override
                        public boolean isCellEditable(int rowIndex, int columnIndex) {
                            return canEdit[columnIndex];
                        }
                    };

y el contenido interno (arreglo bidimensional que se pone en el modelo lo obtiene de una serie de procedimientos).

Gracias por tu ayuda.

Imagen de pechsclk

Analisis

tu quieres retornar todos estos datos

List lst= new LinkedList();
String[] encabezado;
Object[][] modeloInterno;
String mensaje;
boolean bandera;

...
.......
.........

despúes de un procedimiento
en el web service ...

lst.add(encabezado);
lst.add(modeloInterno);
lst.add(mensaje);
lst.add(bandera);

bueno este no entiendo realmente que es lo que vas a hacer

creo que como esta basado en web o webservice es totalmente diferente la cosa
veo que tu quieres mandar el encabezado que es un arreglo
luego veo que tambien esta este  Object[][] modeloInterno; luego siguen mas datos, asi viendolo veo que quieres retornar todo una tabla

que incluira el encabezado...

encabezado1| encabezado2|encabezado3|encabezado4|
dato1 | dato 2 | dato3 | dato4 |
dato5 | dato 6 | dato7 | dato8 |
dato9 | dato 10 | dato11 | dato12 |
dato13 | dato 14 | dato15 | dato16 |

creo que es lo quieres obtener el final desde tu cliente

bueno te puedo dar la idea, pero esto yo lo hago con rmi programa en escritorio

en el servior va esto

public DefaultTableModel cargar_detalle_ajuste_responsiva(String num_responsiva) throws RemoteException;

el que immplementa

@Override
    public DefaultTableModel cargar_detalle_ajuste_responsiva(String num_responsiva) throws RemoteException{
        DefaultTableModel modelo= new DefaultTableModel();
        int registro=0;
        try{
            String[] titulo={"No. Inventario","Descripcion","No. Serie","Marca","Modelo","Color","Costo","No. Factura","F. Asignacion","F. Adquisicion","C. Contable","Proveedor","Observacion"};
            consultar = conec.conx.prepareCall("CALL contar_det_asignacion_ajuste(?)");
            consultar.setString(1, num_responsiva);
            rs=consultar.executeQuery();
            rs.next();
            registro = rs.getInt(1);
            Object[][] datos = new String [registro][titulo.length];
            try{
                consultar = conec.conx.prepareCall("CALL cargar_det_asignacion_ajuste(?)");
                consultar.setString(1, num_responsiva);
                rs=consultar.executeQuery();
                int i=0;
                while(rs.next()){
                    for(int j=0; j<titulo.length; j++){
                        datos[i][j]=rs.getString(j + 1);
                    }
                    i++;
                }
                modelo.setDataVector(datos, titulo);
            }catch(Exception e){
                System.out.println(e);
            }
        }catch(Exception e){
            System.out.println(e);
        }
        return modelo;
    }

en el lado del cliente esta de esta forma

public void num_responsiva(String folio){        
        DefaultTableModel datos;
        try{
            String num_resp = objRemoto.sacar_numero_responsiva_d(folio);
            String[] titulo={"No. Inventario","Descripcion","No. Serie","Marca","Modelo","Color","Costo","No. Factura","F. Asignacion","F. Adquisicion","C. Contable","Proveedor","Observacion"};
            String registro[]=new String[titulo.length];            
            JTableHeader th = tblDetail.getTableHeader();
            Font fuente = new Font("Courier new",Font.BOLD, 14);
            th.setFont(fuente);
            th.setForeground(Color.red);
            modelo = new DefaultTableModel(null, titulo){
                @Override
                public boolean isCellEditable(int filas, int columanas){
                    return false;
                }
            };
// todo esto es lo que hace peticion en el servidor y obtiene una tabla...
            datos = objRemoto.cargar_detalle_ajuste_responsiva(num_resp);
             int vector = datos.getDataVector().size();            
            for (int i = 0; i < vector; i++) {
                for (int j = 0; j < titulo.length; j++) {
                    registro[j] = datos.getValueAt(i, j).toString();
                }
                modelo.addRow(registro);
                tblDetail.setModel(modelo);
            }
            expandir();
        }catch(Exception e){
            System.out.println(e);
        }
    }

bueno yo lo hago de esa forma....
pero como tu dice en
desde un web service o desde un RMI (Spring Remoto) a de ser otro rollo
igual si se puede retornar un DefaultTableMode se puede retornar el arreglo bidimencional
con esto te puede dar una idea..

Imagen de ezamudio

serialización

La lista en sí es serializable, pero tienes que asegurarte que todos los elementos de la misma sean a su vez serializables.

Imagen de adrianaaae

Sip es correcto

Pero seria serializar tanto la clase que regresa (web service o rmi) y la que hace la petición???

Son todas las clases que usan la clase que genera la lista verdad??? Es decir si esa clase usa otras clases también tiene que
serializarse ???

Y en la clase que hace la petición al Web Service o RMI debe de serializarse??? y también sus clases que utiliza??

SI deseo hacer lo que mencione anteriormente que es mejor (RMI o un WS)???

public List returnDet(){
List lst= new LinkedList();
String[] encabezado;
Object[][] modeloInterno;
private List<DefaultTableModel> models = new LinkedList();
String mensaje;
boolean bandera;
...
.......
.........
despúes de un procedimiento
en el web service ...
lst.add(encabezado);
lst.add(modeloInterno);
lst.add(mensaje);
lst.add(bandera);
lst.add(models);

return lst;
}

Imagen de ezamudio

no

La clase que publica el web service no tiene por qué ser serializable. Ni la clase que lo invoca. Pero todos los objetos que se pasan como parámetros en la invocación, y todo el gráfico de objetos en la respuesta, deben ser serializables.

Imagen de Cid

Como dicen en esta respuesta

Como dicen en esta respuesta de stackoverflow

The web services do allow a loosely coupled architecture. With RMI, you have to make sure that the class definitions stay in sync in all application instances, which means that you always have to deploy all of them at the same time even if only one of them is changed (not necessarily, but it is required quite often because of serial UUIDs and whatnot)

Also it is not very scalable, which might be an issue if you want to have load balancers.

In my mind RMI works best for smaller, local applications, that are not internet-related but still need to be decoupled. I've used it to have a java application that handles electronic communications and I was quite satisfied with the results. For other applications that require more complex deployment and work across the internet, I rather use web services.

fuente

Si es standalone local y una aplicación pequeña tomaría sentido usar RMI, de lo contrario un Web Service

Imagen de ezamudio

hay otras opciones

No todo son web services. Todo mundo habla maravillas de los web services, y pues de manera abstracta, son una buena opción, pero el diablo está en las implementaciones. SOAP-RPC en particular es muy ineficiente y hay muchos web services muy mal implementados no sólo internamente sino que sus interfaces son bastante ineficientes, mal diseñadas.

Imagen de Cid

Ok, entiendo que una

Ok, entiendo que una "ventaja" es la interoperabilidad que ofrecen los web services pues RMI no era tan interoperable pero con eso de que ya soporta IIOP que era un protocolo que manejaba CORBA pero pues nunca llegue a utilizar o implementar algo con esa arquitectura, no se si todavía aplique porque en sus comienzos RMI solo soportaba JRMP, esto es cierto ?

Por interoperabilidad me refiero a esto:

RMI permite comunicar aplicaciones java to java (unicamente java)

Web Service comunicar java to X(.net, perl, python, etc ...) o viceversa

Una de las otras opciones que le propones seria hacer un modelo Cliente-Servidor con sockets e hilos ?

Imagen de ezamudio

Exacto

Para comunicación entre aplicaciones, una muy buena opción es manejar comunicación asíncrona en un socket. Puedes usar netty de cada lado para simplificar las cosas.

Imagen de adrianaaae

Y con eso puedo??

Y con eso puedo lograr lo que comentaba, el envio de informacion de cualquier tipo??

O es más para una comunicacion cliente-servidor (envion de datos a través de sockets)

Gracias por su ayuda.

Imagen de ezamudio

envío de datos

Pues a fin de cuentas es envío de datos. RMI es una manera de enviar datos entre distintos procesos Java; a fin de cuentas, es una abstracción sobre sockets y codificación de objetos serializables.

Imagen de adrianaaae

Bueno eso si

Tienes razón, yo lo trate de hacer con Spring Remoto (RMI) pero me marca error de marshalling o algo así.

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">