PDA

Ver la Versión Completa : Problema creacion de ALV OO y refresco


Siem
21/06/10, 21:25:31
Hola compañeros:

Les expongo un caso que me esta ocurriendo y no se muy bien el motivo.

Tengo una primera dynpro 0050 con un ALV el cual tiene varios botones. Algunos de esos botones me abren una dynpro 0200 que sirve para Crear/Modificar/Copiar registros y segun los datos que rellenemos, esta llama a otra dynpro 0300 que continene un ALV orientado a objetos.

En el PBO del dynpro 0300, si no existe, creo el container, el catalogo y el ALVgrid, para finalemente llamar al método ->set_table_for_first_display.

Hasta aqui funciona correcto.

El problema viene cuando desde el dynpro 0050, pulso a un boton dde consulta que llama al dynpro 0300 sin pasar por el 0200. El PBO es el mismo, pero como ya existe el ALV OO, en lugar de crearlo, llamo al metodo ->refresh_table_display. Y me muestra la dynpro 0300 sin ALV. :confused:

He probado a destruir el ALV y crearlo de nuevo y entonces si funciona, pero me hace cosas raras con los datos. Sin embargo, el caso anterior, las tablas internas se mantienen con los datos correctos.

Mi duda es la siguiente:

Puede ser que al crear 0050 --> 0200 --> 0300 --> ALV OO y luego intentar acceder 0050 --> 0300 --> ALV OO haya algun problema por haberme saltado la dynpro 0200?

Disculpad si me he extendido demasiado, pero es que para mi este problema es muy raro.

Muchas gracias por anticipado.

ballan
22/06/10, 13:43:54
Buenos dias

Creo que tu problema esta en como has definido el custom container y el objeto grid

Supongo que en tu programa habras creado el custom container y el control grid con una llamada de este estilo

CREATE OBJECT custom_container
EXPORTING
container_name = 'NOMBRE_CUSTOM_CONTAINER'
lifetime = cntl_lifetime_dynpro
EXCEPTIONS
cntl_error = 1
cntl_system_error = 2
create_error = 3
lifetime_error = 4
lifetime_dynpro_dynpro_link = 5
OTHERS = 6.

La clave es que cuando crees tanto el custom container como el control grid tienes que crearlo pasandole el valor cntl_lifetime_dynpro al parametro lifetime

Haciendolo asi si llamas al metodo free y luego haces un cl_gui_cfw=>flush( ).

Cuando se salga de esa pantalla los objetos "moriran"

El problema es que el parametro lifetime dynpro no se suele rellenar y por defecto es para toda la transaccion, por eso aunque llames al metodo free y hagas un flush los objetos "no mueren"

Disculpas por la explicacion un poco bananera pero espero que se me haya entendido

Siem
23/06/10, 15:20:03
Muchas gracias Ballan.

Bananera o no, por ahora es la unica respuesta que tengo ;)

El caso es que lo que tu propones es destruir el ALV y volverlo a crear, pero esa prueba ya la hice y funcionaba, aunque no se por que, los datos no eran los esperados. El caso es que yo quiero dejar el ALV activo y usarlo cuantas veces me haga falta con el metodo refresh_table_display, modificando solo la tabla interna de la que se nutre.

Aun así, te digo que tu respuesta me ha aportado mas de lo que crees. Muchas gracias.

Pero sigo sin saber por que no me muestra el ALV. Se supone que cuando yo lo creo, lo creo como global para el programa, pero debe depender de algo por ahi que si no existe, no me lo muestra.

A ver si alguien da un poco de luz :) Thx.

ballan
24/06/10, 09:23:16
Yo hace tiempo tuve una experiencia parecida, ya no recuerdo como era el caso exactamente pero yo cambiaba las lineas de mi tabla, hacia un refresh table display y o no me mostraba nada o bien me mostraba datos anteriores

Lo primero de todo es asegurarte que lo que ves es lo que hay y me explico, añade el boton de refrescar en tu alv (si en tu fcat le marcas el edit a algun campo el standard te añade automaticamente entre otros el boton de refrescar) y cuando veas que los datos que te aparecen en pantalla no te cuadran con lo que deberia salir pulsa el boton de refrescar porque a veces ocurre que lo que vemos en pantalla es como una version antigua de los datos

Al fin y al cabo lo que estas teniendo son problemas de sincronizacion entre R3 y el GUI, hace tiempo escribi un post donde hablaba un poco de estos temas, aqui te lo dejo para que lo eches un vistazo por si te puede ser de ayuda

http://www.mundosap.com/foro/showthread.php?t=36251

Otro detalle importante es que despues de hacer un refresh_table_display haz tambien una llamada al cl_gui_cfw=>flush( ). para "asegurarte" que se sincronizan los datos

Siem
25/06/10, 18:15:03
Lo que pasa es que a mi no me muestra el ALV. SOlo sale el dynpro vacio.
Es el mismo efecto que si no existiera el objeto contenedor del alv.

A modo de resumen:

Cuando lo creo:
0050 --> 0200 --> 0300 --> ALV OO
Al hacer el refresh_table_display
0050 --> 0200 --> 0300 --> ALV OO -----> OK
0050 --> 0300 --> ALV OO --------------> No se ve el ALV

Supuestamente el ALV esta asociado al dynpro 0300, pero se ve que debe haber alguna referencia que quede por ahi al crearlo pasando por la dynpro 0200.

Gracias de nuevo.

lehua768
26/06/10, 02:43:25
ya no recuerdo como era el caso exactamente pero yo cambiaba las lineas de mi tabla, hacia un refresh table display y o no me mostraba nada o bien me mostraba datos anterioresLo primero de todo es asegurarte que lo que ves es lo que hay y me explico, añade el boton de refrescar en tu alv (si en tu fcat le marcas el edit a algun campo el standard te añade automaticamente entre otros el boton de refrescar) y cuando veas que los datos que te aparecen en pantalla no te cuadran con lo que deberia salir pulsa el boton de refrescar porque a veces ocurre que lo que vemos en pantalla es como una version antigua de los datosAl fin y al cabo lo que estas teniendo son problemas de sincronizacion entre R3 y el GUI, hace tiempo escribi un post donde hablaba un poco de estos temas, aqui te lo dejo para que lo eches un vistazo por si te puede ser de ayudaEl caso es que lo que tu propones es destruir el ALV y volverlo a crear, pero esa prueba ya la hice y funcionaba, aunque no se por que, los datos no eran los esperados. El caso es que yo quiero dejar el ALV activo y usarlo cuantas veces me haga falta con el metodo refresh_table_display, modificando solo la tabla interna de la que se nutre.

Siem
28/06/10, 05:59:36
ya no recuerdo como era el caso exactamente pero yo cambiaba las lineas de mi tabla, hacia un refresh table display y o no me mostraba nada o bien me mostraba datos anterioresLo primero de todo es asegurarte que lo que ves es lo que hay y me explico, añade el boton de refrescar en tu alv (si en tu fcat le marcas el edit a algun campo el standard te añade automaticamente entre otros el boton de refrescar) y cuando veas que los datos que te aparecen en pantalla no te cuadran con lo que deberia salir pulsa el boton de refrescar porque a veces ocurre que lo que vemos en pantalla es como una version antigua de los datosAl fin y al cabo lo que estas teniendo son problemas de sincronizacion entre R3 y el GUI, hace tiempo escribi un post donde hablaba un poco de estos temas, aqui te lo dejo para que lo eches un vistazo por si te puede ser de ayudaEl caso es que lo que tu propones es destruir el ALV y volverlo a crear, pero esa prueba ya la hice y funcionaba, aunque no se por que, los datos no eran los esperados. El caso es que yo quiero dejar el ALV activo y usarlo cuantas veces me haga falta con el metodo refresh_table_display, modificando solo la tabla interna de la que se nutre.

A ver, centrémonos. El problema no es que el alv me muestre datos incorrectos, o que el metodo de refresco no lo haga correctamente. El problema es que no aparece el ALV, ni botones ni nada. Solo una pantalla vacia, cuando se supone que el contenedor y el ALV estan creados, porque yo en ningun momento los destruyo, y ademas, haciendo el debug, los objetos existen:

IF G_grid_ACT IS INITIAL. " Este es el objeto ALV
PERFORM CREA_ALV_ACT.
ELSE. " En el debugg, se mete por aqui, luego existe el objeto.
CALL METHOD G_GRID_ACT->REFRESH_TABLE_DISPLAY.
ENDIF.

Con lo cual, si existe, no se por que no lo muestra. LAs tablas internas tiene los datos correctos, pero al no mostrar el ALV, no muestra los datos.

Gracias a ti tambien lehua768 :)

ballan
28/06/10, 08:31:11
Ok, habia entendido mal el problema, no obstante todo lo que hemos hablado creo que tambien aplica a tu caso, por ejemplo el fragmento de codigo que me has puesto

IF G_grid_ACT IS INITIAL. " Este es el objeto ALV
PERFORM CREA_ALV_ACT.
ELSE. " En el debugg, se mete por aqui, luego existe el objeto.
CALL METHOD G_GRID_ACT->REFRESH_TABLE_DISPLAY.
ENDIF.

No es del todo correcto

en lugar de preguntar

IF G_grid_ACT IS INITIAL

deberias preguntar (no tengo sap delante por lo que quiza lo que pongo debajo no es del todo correcto sintacticamente pero es para que te hagas una idea)

if g_grid_act->is_alive( ) = g_grid_act->state_alive

En resumen, lo primero que haria es ver cual es el estado REAL del grid, porque puede ser que NO SEA INICIAL, pero por ejemplo si anteriormente han llamado al metodo FREE, aunque el valor del grid no sea inicial ya no seria "utilizable" por lo tanto no te lo mostraria, para poder ver el status puedes introducir el siguiente codigo

data: lv_state type i.

lv_state = g_grid_act->is_alive( ).

Siem
02/07/10, 07:10:32
data: lv_state type i.

lv_state = g_grid_act->is_alive( ).

He probado lo que me has dicho, y esta linea, aunque compila correctamente, me devuelve un dump. ???

No entiendo por que porque mira que es simple la instruccion :)


El metodo is_alive( ) nofunciona en mi sistema. Que raro.

ballan
02/07/10, 11:11:04
Si te esta dando dump puede ser porque la clase no este instanciada o bien porque no devuelva un valor de tipo i, no tengo sap delante asi que no te lo puedo mirar pero si te fijas en la clase CL_GUI_ALV_GRID en los parametros del metodo IS_ALIVE fijate en cual es el tipo que te devuelve, yo creia que era tipo I pero puede ser que sea alguno diferente

El codigo quedaria algo asi

data: lv_state type (tipo que hayas visto en la clase CL_GUI_ALV_GRID).

if not g_grid_act is initial.
lv_state = g_grid_act->is_alive( ).
endif.

Siem
02/07/10, 11:49:29
Lo habia mirado ya y es correcto el tipo que habias puesto. Es de tipo i.

El simple hecho de llamar al metodo is_alive, me da un dump, y no deberia

ballan
02/07/10, 12:16:50
Pero g_grid_act es inicial o no?

Pegame el dump para que veamos que es lo que pasa

Siem
02/07/10, 12:44:00
A modo de resumen:

Cuando lo creo:
0050 --> 0200 --> 0300 --> ALV OO
Al hacer el refresh_table_display
0050 --> 0200 --> 0300 --> ALV OO -----> OK
0050 --> 0300 --> ALV OO --------------> No se ve el ALV

He hecho la prueba al reves y tampoco va.

Cuando lo creo:
0050 --> 0300 --> ALV OO
Al hacer el refresh_table_display
0050 --> 0200 --> 0300 --> ALV OO -----> No se ve el ALV
0050 --> 0300 --> ALV OO --------------> OK

Pero g_grid_act es inicial o no?

Pegame el dump para que veamos que es lo que pasa

La primera vez que intento acceder a la dynpor 0300, evidentemente es initial, por lo que crea el ALV y lo muestra correctamente. Si vuelvo a acceder por el mismo camino,el refresh_table_display lo muestra correctamente. Pero si ahora accedo por el otro camino (Sin pasar por la dynpro 0200) el refresh_table_display no muestra el alv. En este caso el
g_grid_act no es initial.


Pego ahora el dump que da el metodo is_alive( )

Texto breve
Access via 'NULL' object reference not possible.

¿Qué ha sucedido?
Error in the ABAP Application Program

The current ABAP program "ZRFCTA_DEPOS" had to be terminated because it has come across a statement that unfortunately cannot be executed.

Anál.errores
An exception occurred that is explained in detail below.
The exception, which is assigned to class 'CX_SY_REF_IS_INITIAL', was not caught in procedure "STATUS_0300" "(FORM)", nor was it propagated by a RAISING clause.
Since the caller of the procedure could not have anticipated that the exception would occur, the current program is terminated.
The reason for the exception is:
You attempted to use a 'NULL' object reference (points to 'nothing')
access a component (variable: "G_GRID_ACT").
An object reference must point to an object (an instance of a class)
before it can be used to access components.
Either the reference was never set or it was set to 'NULL' using the
CLEAR statement.

Eso es lo que me dice, simplemente por poner la linea:

DATA lv_state type i.

>>>>> lv_state = g_grid_act->is_alive( ).


De nuevo muchas gracias por tu tiempo, Ballan :)

ballan
02/07/10, 13:49:37
El dump te esta dando porque g_grid_act es inicial, esta intentando llamar a un metodo de un objeto que no esta instanciado

Bien yo creo que aqui se abren dos caminos y tendria que ver el codigo para saber lo que esta pasando exactamente pero te digo las opciones que hay tal y como yo lo veo

Opcion 1.- Corregir el algoritmo para la creacion o refresco del ALV

Deberia quedar algo mas o menos asi


DATA: lv_state TYPE i.

IF g_grid_act IS INITIAL.
....CREAR OBJETO GRID
ELSE.

"Al llamarlo aqui evitaras que de dump porque g_grid_act nunca sera inicial
lv_state = g_grid_act->is_alive( )

IF lv_state = g_grid_act->state_dead.
CREAR OBJETO GRID
ELSE.
REFRESCAR OBJETO GRID
ENDIF.

ENDIF.


Opcion 2 Tendria que ver el codigo, pero es posible que en algun momento se este llamando al metodo free de g_grid_act o bien que lo hayas creado con lifetime_dynpro y al hacer alguna operacion el objeto se "libera" automaticamente, con esto lo que quiero decir es que por ejemplo puede ser que tu veas que g_Grid_act NO ES INICIAL, es decir que contiene "algo" pero realmente eso es falso porque luego si llamas al metodo IS_ALIVE te devuelve state_dead

Si te devuelve state_dead tendras que crearlo aunque no sea inicial porque la unica la razon por la que no es inicial es porque todavia no ha pasado el "garbage collector" (aunque este concepto es mas de otros lenguajes)

Para explicar esto pongo un ejemplo, si yo escribiera el siguiente codigo


DATA: go_cc TYPE REF TO cl_gui_custom_container,
go_grid TYPE REF TO cl_gui_alv_grid.

"Voy a obviar los parametros al crear
CREATE OBJECT go_cc.

CREATE OBJECT go_grid.

go_grid->free( ).

Si yo en este punto del programa miro la variable go_grid vere que NO ES INICIAL, esta rellena pero realmente el objeto grid ya no es utilizable porque ya lo mande "morir" asi que tendria que crearlo otra vez



Asi que tambien deberias buscar si en algun sitio se esta haciendo un free ya sea del objeto grid o del container sobre el que esta definido y es eso lo que te esta trastocando

Siem
05/07/10, 05:41:47
Yo me inclino mas por la segunda opcion, pero: ¿Que pasa si el parámetro lifetime no esta indicado? ¿Toma algun valor por defecto?.Si se queda con state_dead al cerrar la dynpro donde se creo el ALV, pues entonces estará ahi el problema, aunque si vuelvo a llamar a la dynpro porel mismo camino,el ALV sigue ahí. Si la llamo por otro camino, el ALV no aparece.

La aplicacion la he hecho yo al completo, asi que se que no hay ningun free en el codigo.

De todos modos, hay una cosa que no entiendo. Y es que como puede dar un dump, el metodo IS_ALIVE si precisamente sirve para ver si existe o no.

ballan
08/07/10, 10:09:18
Si el parametro lifetime no esta indicado por defecto toma lifetime_transaction
que significa que el control existira mientras exista el modo que lo creo

El metodo IS_ALIVE es un metodo de instancia, lo que significa que tienes que tener la clase instanciada (has tenido que hacer previamente un create object)
si te da dump es porque la clase no esta instanciada o porque el lifetime ha expirado y el objeto ha "muerto" (aunque tu debugenado veas que la variable NO ES INICIAL)

De hecho hablar de INITIAL para variables declaradas con type ref no es del todo correcto por esta razon, para objetos type ref en lugar de utilizar IS INITIAL seria mas correcto utilizar IS BOUND

Jonathan Barrio
09/07/10, 12:37:35
Ya no me acuerdo de esto de los objetos y los ALV.

Pero? para llamar a los metodos no tenían que estár capturados mediante una sentencia? Cómo el del doble click...

¿ Si en vez de preguntar si es initial o llamar a ese metodo haces un
IF objeto IS BOUND.
ENDIF.
podría valer ?

DavidXD_XD
09/07/10, 14:28:11
Hola, a mi me ha tocado hace poco realizar ese tipo de tratamiento de objetos con 2 ALV, uno que siempre existira y el cual llama a otro para mostrar diferentes reportes a partir de un solo contenedor, lo que pasaba era que en la primera ejecucion de la segunda pantalla siempre funcionaba y me mostraba x ejemplo 5 registros, luego regresaba a la pantalla anterior y cuando modificaba datos en otras transaccion para que se reflejara cambios en la segunda pantalla resulta q siempre me salian esos 5 registros y nunca refrescaba, pero justo trabaje con una funcion llamada MD_PEGGING y en la ultima parte llama a un screen 1000, esa funcion me muestra un ALV y en el cual a la hora de darle BACK, EXIT o CANCEL te mata todos los objetos

1. Ir a la parte final de la funcion y entrar al dynpro 1000
2. Ir al module check_fcode
3. No tomar en cuenta el cl_gui_cfw=>dispatch xq matara tu primer ALV
4. Ir al PERFORM check_fcode
5. Ir al PERFORM exit_from_alv el cual como veras se encuentra habilitado para los botones BACK, ENDE, STOP, OTHR
6. Mirar la rutina y de que manera mata los objetos para que cuando los vuelvas a llamar nuevamente los instancies (CREATE OBJECT) como si fuera la primera vez
7. Fijate que mata sobretodo el grid y el contenedor con un metodo publico de instancia FREE, y luego al final matas la instancia de la clase local si es que has creado el ALV desde una ...

Espero q esta info t sirva xq yo lo aplique y si me funciono ...

PD: Lei el primer post y los 3 ultimos xq son un monton :D, y tal vez estoy dando una mala interpretacion del problema :o

Siem
14/07/10, 19:56:15
Si el parametro lifetime no esta indicado por defecto toma lifetime_transaction
que significa que el control existira mientras exista el modo que lo creo

El metodo IS_ALIVE es un metodo de instancia, lo que significa que tienes que tener la clase instanciada (has tenido que hacer previamente un create object)
si te da dump es porque la clase no esta instanciada o porque el lifetime ha expirado y el objeto ha "muerto" (aunque tu debugenado veas que la variable NO ES INICIAL)

De hecho hablar de INITIAL para variables declaradas con type ref no es del todo correcto por esta razon, para objetos type ref en lugar de utilizar IS INITIAL seria mas correcto utilizar IS BOUND

Disculpa que haya tardado en responder, pero es que he estado un poco enfermo. (Los aires acondicionados, que son muy traicioneros).

El IS BOUND tambien lo habia probado, pero el resultado es el mismo.

Si el lifetime es por defecto lifetime_transaction (yo no pongo nada en ese parametro, asi que debe serlo) y eso quiere decir que debe durar mientras dure el modo, entonces puede ser ese el problema.

¿Cuando haces un CALL SCREEN 0300 STARTING AT 20 5, se supone que la ventana modal que abre es otro modo? Si es eso, entonces esta claro que si el ALV, al haber cerrado la ventana donde se creo, no me permite hacer el metodo refresh_table_display.


DavidXD_XD, el problema que comentas me suena que me ha pasado cuando uso el plan B, que es destruir el ALV y volverlo a crear. En ese caso el ALV me mostraba algo distinto a mi tabla interna, pero creo recordar que la primera vez si lo mostraba correctamente. Se parece mucho al problema que comentas.

Gracias a los dos. Parece que ya va estando mas cerca la explicacion de este problema.