Sei sulla pagina 1di 79

Nuevas funcionalidades para desarrolladores de

ORACLE 9i y 10g.

Nuevas funcionalidades
para desarrolladores de
ORACLE 9i y 10g.

Toledo, mayo de 2007

1 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Índice.
1. Mejoras en PL/SQL y SQL......................................................................................3
a. Mejoras en SQL.................................................................................................3
i. Mejoras incorporadas en la 9i.........................................................................3
ii. Mejoras incorporadas en la 10g......................................................................6
iii. Encriptación....................................................................................................7
b. Mejoras en PL/SQL............................................................................................8
i. Mejoras incorporadas en la 9i.........................................................................8
ii. Mejoras incorporadas en la 10g....................................................................10
c. La papelera de reciclaje:...................................................................................11
d. XML..................................................................................................................12
i. Conceptos básicos de XML...........................................................................12
e. JAVA en ORACLE............................................................................................15
i. Conceptos básicos de JAVA..........................................................................15
ii. Procedimientos almacenados JAVA..............................................................16
iii. Creación de objetos JAVA.............................................................................16
iv. JDBC.............................................................................................................16
v. SQLJ.............................................................................................................18
2. Instalación de Oracle Developer Suite 10g (10.1.2.0.2) para Windows...............20
3. Forms Builder. Diferencias entre las versiones 6i y 10g........................................29
a. Diferencias en el Navegador de Objetos:.........................................................29
b. Diferencias en el Editor de Informes:................................................................30
c. Diferencias en las Propiedades:.......................................................................31
d. Propiedades que cambian de 6i a 10g:............................................................32
e. Diferencias en las Paquetes incorporados, constantes y disparadores:...........33
f. Diferencias en el Editor PL/SQL:......................................................................37
g. Procedimientos................................................................................................38
h. Árbol jerárquico................................................................................................43
i. JAVA en Forms Developer................................................................................46
i. Entorno..........................................................................................................46
ii. Usando JAVA en Developer...........................................................................47
j. ANEXO A. Herramientas de migración.............................................................62
4. Report Builder. Diferencias entre las versiones 6i y 10g.......................................63
a. Diferencias en el Navegador de Objetos:.........................................................63
b. Diferencias en el Editor de Diseño:..................................................................66
c. Orígenes de datos:...........................................................................................69
d. Diferencias en las Propiedades:.......................................................................72
e. Plantillas........................................................................................................... 73
f. JSP con Developer Report 10g........................................................................76
i. Conceptos Básicos........................................................................................76
ii. reports_tld.jar................................................................................................78

2 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

1. Mejoras en PL/SQL y SQL.


a. Mejoras en SQL.
i. Mejoras incorporadas en la 9i

Nuevos tipos de datos


TIMESTAMP extensión de DATE
VARCHAR2(N CHAR|BYTE) y CHAR(N CHAR|BYTE)

ALTER TABLE
Se puede renombrar columnas de una tabla:
ALTER TABLE nombre_de_tabla
      RENAME COLUMN nombre_columna TO nuevo_ nombre_columna

Funciones para intervalos de tiempo.


Útil para el manejo de datos de fecha y hora.

Para intervalos de días, horas, minutos y segundos:


INTERVAL ‘entero o/y expresión de tiempo’ DAY|HOUR|MINUTE|SECOND 
          [(precisión[,fración de segundo])] 
          [TO DAY|HOUR|MINUTE|SECOND[(fración de segundo)]]
Para intervalos de años o meses:
INTERVAL ‘entero[­entero]’ YEAR|MONTH [(precisión)] [TO YEAR|MONTH]

Las operaciones que se pueden hacer con los intervalos pueden ser:
Operando 1 Operador Operando 2 Resultado
Datetime + Intervalo Datetime
Datetime - Intervalo Datetime
Intervalo + Datetime Datetime
Datetime - Datetime Intervalo (No Datetime)
Intervalo + Intervalo Intervalo
Intervalo - Intervalo Intervalo
Intervalo * Numerico Intervalo
Numerico * Intervalo Intervalo
Intervalo / Numerico Intervalo

3 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Mejoras en SELECT:
CASE:
CASE CAMPO 
WHEN expresión THEN varlor de retorno […]
[ ELSE varlor de retorno ]
END

COALESCE:
COALESCE (campo|expresión [,…])
Si el primer campo|expresión es NULL, devuelve el siguiente, y así sucesivamente.

NULLIF:
NULLIF(expresión, expresion2)
Compara las expresiones, y si son iguales, devuelve NULL.

CURSOR:
CURSOR(‘consulta’), devuelve un refCursor

4 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

IS OF
Expressión IS [NOT] OF [TYPE] ([ONLY] TIPO)
Cierto si la expresión es del mismo tipo que TIPO

Joins:
Referencia_tabla1 Tipo_join JOIN Referencia_tabla2
{ON condición | USING (columna [,…])}
ó
Referencia_tabla1 {CROSS | NATURAL Tipo_join } JOIN Referencia_tabla2

Donde Tipo_join puede ser:


[ {INNER | {LEFT|RIGHT|FULL} [OUTER]} ]

INNER  Muestra los datos que coincidan en Referencia_tabla1 y Referencia_tabla2,


según la condición de ON o USING.
LEFT  Muestra los datos que coincidan en Referencia_tabla1 y Referencia_tabla2,
según la condición de ON o USING, y los datos que no coincidan de Referencia_tabla1
RIGHT Muestra los datos que coincidan en Referencia_tabla1 y Referencia_tabla2,
según la condición de ON o USING, y los datos que no coincidan de Referencia_tabla2
FULL  Muestra los datos que coincidan en Referencia_tabla1 y Referencia_tabla2,
según la condición de ON o USING, y los datos que no coincidan de Referencia_tabla1 y
Referencia_tabla2
OUTER  Para aclarar la sintaxis.
CROSS  Referencia_tabla1, Referencia_tabla2, producto cartesiano.
NATURAL  Es como un USING, pero de los campos que se llamen igual en las
referencias a tablas.

SELECT jerárquicos:
SYS_CONNECT_BY_PATH(campo,’carácter’)
Concatena los niveles por ‘carácter’

5 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

ii. Mejoras incorporadas en la 10g


Nuevos tipos de datos:
 BINARY_FLOAT
 BINARY_DOUBLE

SELECT jerárquicos:
CONNECT_BY_ROOT campo
Muestra el raiz, el padre de la rama de la consulta
CONNECT_BY_ISCYCLE  campo
Indica 1 si es un elemento que se enlaza a si mismo
CONNECT_BY_ISLEAF campo
Indica 1 si es una hoja, es decir, no es elemento raíz

Expresiones regulares:
Operador Descripción
[caracteres] Indicamos que debe de ser uno de los caracteres indicados. Se
pueden usar rangos, [a-m] letras de a a m.
[^caracteres Indicamos que NO es uno de los caracteres indicados.
]
[:alnum:] Caracteres de tipo alfanumérico, igual que [0-9A-Za-z
[:alpha:] Caracteres de tipo alfabético.
[:digit:] Caracteres de tipo dígito.
[:lower:] Carácter inicial de tipo alfabético, y en minúsculas.
[:space:] Carácter espacio.
[:upper:] Carácter inicial de tipo alfabético, y en mayúsculas.
^ Inicio de línea.
$ Final de línea.
. Cualquier carácter.
? Uno o ningún carácter.
\símbolo Si quiero buscar líneas que contengan | o $ o + etc.
\n Indica un campo n. Se usa en las sustituciones. Los campos se
indican con (expresión)
r1|r2 O r1 ó r2.
r+ De una a más concurrencias de r.
r* De cero a más concurrencias de r.
r? De cero a una concurrencia de r.
r{n} n concurrencias consecutivas de r.
r{n,} n o menos concurrencias consecutivas de r.
r{n,m} entre n y m concurrencias consecutivas de r.

Funciones para manejar expresiones regulares.


REGEXP_INSTR
REGEXP_INSTR (expresión, ‘expresión regular’ [, inicio] [, ocurrencias] [, 
opción de retorno] [, parámetros de búsqueda] 
Devuelve donde se encuentra la ocurrencias de la ‘expresión regular’ a partir 
inicio, según opción de retorno y parámetros de búsqueda
opción de retorno:
0 Devuelve el principio donde se encuentra la ocurrencia.
1 Devuelve el final donde se encuentra la ocurrencia.

6 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

parámetros de búsqueda:
i  Insensible a mayúsculas y minúsculas.
c Sensible a mayúsculas y minúsculas.
m Indica que la expresión se compone de múltiples líneas
x Ignora los espacios en blanco

REGEXP_REPLACE
REGEXP_REPLACE (expresión, ‘expresión regular’, ‘cadena que reemplaza’ [, 
inicio] [, ocurrencias] [, parámetros de búsqueda] 
Sustituye en la expresión, la ‘expresión regular’ por ‘cadena que reemplaza’, según
inicio, ocurrencias y parámetros de búsqueda.
Se pueden usar los campos “\n”.

REGEXP_SUBSTR
REGEXP_SUBSTR (expresión, ‘expresión regular’, [, inicio] [, ocurrencias] [, 
parámetros de búsqueda] 
Devuelve una subcadena que cumple la ‘expresión regular’, según inicio,
ocurrencias y parámetros de búsqueda.

REGEXP_LIKE
REGEXP_LIKE (expresión, ‘expresión regular’ [, parámetros de búsqueda] 
Devuelve True si la expresión cumple la ‘expresión regular’.

Mejoras en SELECT:
IS NAN|INFINITE
Devuelve true si la expresión no es un número o ±INF.

IS EMPTY
Expresión IS [NOT] EMPTY
Devuelve true si la expresión está vacia. El NULL lo considera como valor.

iii. Encriptación
Se puede indicar al ORACLE que una columna de una tabla encripte su valores de
forma transparente al usuario final. Se indica como una restricción, usando la sintaxis:
Definición de columna ENCRYPT [ USING ’{3DES168 | AES128 | AES192 | AES256 }
’] [ IDENTIFIED BY contraseña] [ [NO] SALT]

Si la columna es clave, se debe de especificar NO SALT.


No se deben de encriptar columnas de clave foránea.
Si la contraseña no se pone, se usa la indicada por el administrador de la base de
datos (WALLET).

7 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

b. Mejoras en PL/SQL.
i. Mejoras incorporadas en la 9i

Arrays asociativos.
Son como los hash de perl, es decir, el índice de la tabla no es un número, sino unas
claves.
TYPE tipo_tabla IS TABLE OF NUMBER INDEX BY VARCHAR2(N);

Mejora del paquete UTL_FILE.

Integración del analizador de errores de SQL y PL/SQL.

CASE.
Como expression:
Vble := CASE selector
 {WHEN expresion1 THEN resultado1;} [WHEN …]
 [ELSE resultadoN+1]
END;
Como instrucción:
CASE
 { WHEN expresión booleana THEN {comandos;} [WHEN …]
 [ELSE {comandos;}... ]
END CASE 

Compilación de código nativo con PL/SQL.

Bulk Dynamic SQL


Usar tipos records para DML de SQL.
 INSERT En VALUES se indica el records que se quiere insertar.
INSERT INTO tabla VALUES registro
 UPDATE Se puede indicar que se modifica un registro entero a partir de un
records:
UPDATE tabla SET ROW = registro WHERE condición
 INSERT, UPDATE, DELETE La fila afectada se puede guardar en un record.
DML RETURNING campo [,…] INTO registro;

8 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

EXECUTE IMMEDIATE
EXECUTE IMMEDIATE ‘CADENA’ [INTO VBLE [,…]|REGISTRO] 
        [USING [[{IN|OUT|IN OUT}] VBLE [,…]] 
        [{RETURN|RETURNING} INTO VBLE [,…]]
Ejecuta el comando especificado en ‘CADENA’. Si el comando es del tipo ‘… INTO …’,
se usa INTO para indicar a donde se guarda la información, no confundir con RETURN o
RETURNING, ya que esto indica donde se guarda la información cuando se usa
RETURNING en las instrucciones DML. Si se quiere usar parámetros dentro del
comando especificado en la ‘CADENA’, se indican sus valores en USING.

BULK COLLECT
En los comandos que usen INTO (SELECT, FETCH ó cláusula RETURNING ), se puede usar
la cláusula BULK COLLECT, que indica que los datos se guardan en una elemento de tipo
TABLE. No lanza la excepción NO_DATA_FOUND

FORALL
Es igual al FOR, pero es mucho más rápido que el FOR clásico, cuando en el cuerpo
del bucle se encuentran comandos DML. Se puede usar la variable SQL
%BULK_ROWCOUNT(I), que indica las filas afectadas en la I vuelta del bucle.

9 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

ii. Mejoras incorporadas en la 10g


Nuevo tipos de dato:
 PLS_INTEGER

FORALL
Se puede usar el record  %BULK_EXCEPTIONS(I),  con los campos  ERROR_INDEX  y
ERROR_CODE que indica el error DML en la I vuelta del bucle.

Conditional Compilation
Podemos usar directivas que controlan el comportamiento del preprocesador, de forma
que este puede ignorar o compilar determinadas líneas del código PL/SQL en función
de ciertas condiciones que son evaluadas durante el preproceso. Para ello tenemos la
siguiente directiva:
$IF expresión Booleana $THEN texto
[ $ELSIF expresión Booleana $THEN texto ]
[ $ELSE texto ]
$END
En expresión Booleana podemos usar:
 $$PLSQL_LINE Devuelve la línea del código PL/SQL
 DBMS_DB_VERSION.{VER_LE_9 | VER_LE_9_1 | VER_LE_9_2 | VER_LE_10
| VER_LE_10_1 | VER_LE_10_2} Devuelve TRUE si la versión de ORACLE
corresponde con VER_LE_XX
 DBMS_DB_VERSION.VERSION Devuelve el número de versión de ORACLE.

También podemos lanzar errores de compilación de usuario con la directiva:


$ERROR ‘cadena’ $END

10 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

c. La papelera de reciclaje:
Las nuevas versiones de ORACLE, nos proporcionan una especie de papelera de
reciclaje

Consultas para manejar la papelera de reciclaje:


Para ver el contenido total de la papelera:
SELECT * FROM RECYCLEBIN;

Para ver el contenido de la papelera del usuario:


SELECT * FROM USER_RECYCLEBIN;

Comandos para manejar la papelera de reciclaje:


CREATE RESTORE POINT
Creamos un punto de restauración, que después usaremos con FLASHBACK TABLE,
para poder recuperar filas que han sido manipuladas por DML
CREATE RESTORE POINT nombre_punto_restauración

FLASHBACK TABLE
Con FLASHBACK TABLE indicamos que la tabla se recupere de la papelera de
reciclaje cuando se borra (BEFORE   DROP) o que se recuperen los cambios que se
producen con DML (SCN | TIMESTAMP …| RESTORE POINT). Para esto último tenemos
que habilitar en la tabla la propiedad ROW MOVEMENT (ALTER TABLE tabla ENABLE
ROW MOVEMENT)
FLASHBACK TABLE tabla TO { {{SCN | TIMESTAMP} expr 
                             | RESTORE POINT punto_restauración}  
                           [ { ENABLE | DISABLE}  TRIGGERS ] } 
                         | BEFORE DROP [ RENAME TO tabla] };

Si queremos ver los valores antiguos de las filas que han sido manipuladas con DML,
podemos usar en el SELECT la cláusula AS OF:
  [ VERSIONS BETWEEN { SCN | TIMESTAMP} { expr | MINVALUE } AND
                                        {expr | MAXVALUE }] 
AS OF {SCN | TIMESTAMP} expr

PURGE
Con PURGE manipulamos la papelera. La opción RECYCLEBIN vaciara la papelera
completamente del usuario.
PURGE {TABLE tabla | INDEX índice | RECYCLEBIN };

PURGE es también un parametro del comando DROP, he indica que el objeto que se
va a eliminar no se almacene en la papelera (si previamente se ha usado con ella el
comando FLASHBACK TABLE). Un ejemplo:
DROP TABLE nombre_tabla PURGE;

11 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

d. XML.
i. Conceptos básicos de XML
(wikipedia)XML, sigla en inglés de eXtensible Markup Language («lenguaje de marcas
extensible»), es un metalenguaje extensible de etiquetas desarrollado por el World
Wide Web Consortium (W3C). Es una simplificación y adaptación del SGML y permite
definir la gramática de lenguajes específicos (de la misma manera que HTML es a su
vez un lenguaje definido por SGML). Por lo tanto XML no es realmente un lenguaje en
particular, sino una manera de definir lenguajes para diferentes necesidades. Algunos
de estos lenguajes que usan XML para su definición son XHTML, SVG, MathML.
XML no ha nacido sólo para su aplicación en Internet, sino que se propone como un
estándar para el intercambio de información estructurada entre diferentes plataformas.
Se puede usar en bases de datos, editores de texto, hojas de cálculo y casi cualquier
cosa imaginable.
XML es una tecnología sencilla que tiene a su alrededor otras que la complementan y
la hacen mucho más grande y con unas posibilidades mucho mayores. Tiene un papel
muy importante en la actualidad ya que permite la compatibilidad entre sistemas para
compartir la información de una manera segura, fiable y fácil.

Documentos XML bien formados


Se llama documentos "bien formados" (del inglés well formed) a los documentos que
cumplen con todas las definiciones básicas de formato y pueden, por lo tanto, ser
analizados correctamente por cualquier analizador sintáctico (parser) que cumpla con
la norma. Se separa esto del concepto de validez que se explica más adelante.
 Los documentos han de seguir una estructura estrictamente jerárquica con lo
que respecta a las etiquetas que delimitan sus elementos. Una etiqueta debe
estar correctamente incluida en otra, es decir, las etiquetas deben estar
correctamente anidadas. Los elementos con contenido deben estar
correctamente cerrados.
 Los documentos XML sólo permiten un elemento raíz del que todos los demás
sean parte, es decir, sólo puede tener un elemento inicial.
 Los valores atributos en XML siempre deben estar encerrados entre comillas
simples o dobles.
 El XML es sensible a mayúsculas y minúsculas. Existe un conjunto de
caracteres llamados espacios en blanco (espacios, tabuladores, retornos de
carro, saltos de línea) que los procesadores XML tratan de forma diferente en
el marcado XML.
 Es necesario asignar nombres a las estructuras, tipos de elementos, entidades,
elementos particulares, etc. En XML los nombres tienen alguna característica
en común.
 Las construcciones como etiquetas, referencias de entidad y declaraciones se
denominan marcas; son partes del documento que el procesador XML espera
entender. El resto del documento entre marcas son los datos entendibles por
las personas.

Validez
Que un documento sea "bien formado" solamente habla de su estructura sintáctica
básica, es decir que se componga de elementos, atributos y comentarios como XML
manda que se escriban. Ahora bien, cada aplicación de XML, es decir cada lenguaje

12 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

definido con esta tecnología, necesitará especificar cuál es exactamente la relación


que debe verificarse entre los distintos elementos presentes en el documento.
Esta relación entre elementos se especifica en un documento externo o definición
(expresada como DTD (Document Type Definition = Definición de Tipo de Documento)
o como XSchema). Crear una definición equivale a crear un nuevo lenguaje de
marcado, para una aplicación específica.

Document type definition (DTD)


La DTD define los tipos de elementos, atributos y entidades permitidas, y puede
expresar algunas limitaciones para combinarlos. Los documentos XML que se ajustan
a su DTD se denominan válidos.

XML Schemas (XSD)


Un Schema es algo similar a un DTD, define que elementos puede contener un
documento XML, como están organizados y que atributos y de que tipo pueden tener
sus elementos.
Ventajas de los Schemas frente a los DTDs
 Usan sintaxis de XML, al contrario que los DTDs.
 Permiten especificar los tipos de datos.
 Son extensibles.

Tecnologías XML (Las más comunes)


 Extended Stylesheet Language (XSL) EL Lenguaje de Hoja de Estilo Extensible
es una familia de lenguajes que permiten describir como los archivos
codificados en xml serán formateados(para mostrarlos) o transformados. Hay
tres lenguajes en esta familia: XSL Transformations (XSLT), XSL Formatting
Objects (XSL-FO)y XML Path Language.
 XSLT o XSL Transformaciones es un estandar de la organización W3C que
presenta una forma de transformar documentos XML en otros e incluso a
formatos que no son XML. Las hojas de estilo (aunque el termino de hojas de
estilo no se aplica sobre la función directa del XSLT) XSLT realizan la
transformación del documento utilizando una o varias reglas de plantilla: unidas
al documento fuente a transformar, esas reglas de plantilla alimentan a un
procesador de XSLT, el cual realiza las transformaciones deseadas colocando
el resultado en un archivo de salida o, como en el caso de una página web,
directamente en un dispositivo de presentación, como el monitor de un usuario.
 XSL-FO Un documento XSL-FO es un documento XML en el que se especifica
cómo se van a formatear unos datos para presentarlos en pantalla, papel u
otros medios. El significado de las siglas XSL-FO es eXtensible Stylesheet
Language Formatting Objects. Hay que destacar que en el documento XSL-FO
figuran tanto los datos como el formato que se les va a aplicar.
 XPath (XML Path Language) es un lenguaje que permite construir expresiones
que recorren y procesan un documento XML. La idea es parecida a las
expresiones regulares para seleccionar partes de un texto sin atributos (plain
text). XPath permite buscar y seleccionar teniendo en cuenta la estructura
jerárquica del XML. XPath fue creado para su uso en el estándar XSLT, en el
que se usa para seleccionar y examinar la estructura del documento de entrada
de la transformación.
 SAX son las siglas de "Simple API for XML", originalmente, una API
únicamente para el lenguaje de programación JAVA, que después se convirtió

13 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

en la API estándar de facto para usar XML en JAVA. Existen versiones de SAX
no sólo para JAVA, si no también para otros lenguajes de programación.
 DOM Document Object Model (en español ‘Modelo de Objetos de Documento’),
frecuentemente abreviado DOM, es una forma de representar los elementos de
un documento estructurado (tal como una página web HTML o un documento
XML) como objetos que tienen sus propios métodos y propiedades. El
responsable del DOM es el World Wide Web Consortium (W3C).

XML y ORACLE
Desde Oracle9i release 1 (9.0.1) se ha creado un nuevo tipo de dato, XMLType, que
facilita el manejo de documentos XML.
Anteriormente, se usaba un CLOB, VARCHAR, etc. para guardar documentos XML en
la base de datos. Los paquetes más importantes para el uso de XML en ORACLE son:
 Paquete DBMS_XMLDOM. Este paquete nos proporciona lo necesario para
usar Document Object Model (DOM).
 Paquete DBMS_XMLSTORE. Este paquete nos proporciona herramientas para
poder convertir un documento XML a información relacional, es decir, a
información que se puede guardar en la base de datos.
 Paquete DBMS_XMLPARSER. Este paquete nos proporciona lo necesario
para comprobar si un documento XML es valido y está bien formado.
 Paquete DBMS_XMLGEN. Este paquete nos proporciona herramientas para
poder generar documentos XML a partir de datos de la base de datos, es
similar al paquete DBMS_XMLQUERY.

14 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

e. JAVA en ORACLE.
i. Conceptos básicos de JAVA.
(wikipedia)JAVA es un lenguaje orientado a objetos (clases). Es muy parecido a C++.
Los programas en Java son compilados a un lenguaje intermedio llamado bytecode,
que luego son interpretados por una máquina virtual (JVM). Esta última sirve como una
plataforma de abstracción entre la máquina y el lenguaje permitiendo que se pueda
"escribir el programa una vez, y correrlo en cualquier lado".

Clases
Son declaraciones o abstracciones de objetos, es decir, es la definición de un objeto,
con sus atributos y métodos.

Clases abstractas
Sirven para declarar un interfaz común a un conjunto de clases. Los métodos sólo se
declaran, no se implementan, de ello se encargarán las clases hijas.
Se declaran con abstract. No se pueden instanciar. Al menos un método de la clase es
abstracto.

Interfaces
Es parecido a las clases abstractas. Pero la mayor diferencia radica que una clase
puede “heredar” de varias interfaces.

Herencia en JAVA.
No existe la herencia múltiple como en C++, solo se puede heredar de una sola clase.
Las clases de java, son siempre descendientes de forma implícita, de la clase Object.
Para indicar que una clase hereda de otra (abstracta o normal), se usa la palabra clave
extends.
Cuando se “hereda” de un interfaz, se usa la palabra clave implements. Se pueden
implementar uno o varios interfaces.

Paquetes
Son agrupaciones de clases e interfaces comunes. Si declaro una clase dentro del
paquete demo.oracle.conexion, llamada validar, esa clase se encuentra en
$CLASS_PATH/demo/oracle/conexión. Cuidado con las mayúsculas, aunque
estemos en entornos Windows.

Bean.
Un Bean es un componente software que tiene la particularidad de ser reutilizable y
así evitar la tediosa tarea de programar los distintos componentes uno a uno. Se
puede decir que existen con la finalidad de ahorrarnos tiempo al programar. Es el caso
de la mayoría de componentes que manejan los editores visuales más comunes. Bean
viene del inglés "fríjol", y su idea principal es que se reaprovechan "frijoles" que ya han
sido creados por otros desarrolladores. Sabiendo esto, un Bean puede representar
desde un botón, un grid de resultados, un panel contenedor o un simple campo de
texto, hasta otras soluciones mucho más complejas como conexiones a bases de
datos, etc.

15 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

ii. Procedimientos almacenados JAVA


Con loadjava se cargan clases en oracle a través de la consola. La sintaxis
simplificada del comando es:
loadjava [­oci8] [­thin]  [­schema esquema] [­tableschema esquema] 
[­user usuarior/password@base de datos] [­verbose] 
classes..jars..resources..properties...

Y con dropjava se eliminan:


dropjava [­oci8] [­thin]  [­schema esquema]
[­user usuarior/password@base de datos] [­verbose] 
classes..jars..resources..properties...

iii. Creación de objetos JAVA


Se pueden crear objetos en la base de datos que contengan clases o código JAVA con
CREATE JAVA
CREATE [OR REPLACE] [AND COMPILE] [NOFORCE] 
JAVA { {SOURCE | RESOURCE} NAMED identificador_objeto
     | CLASS [ SCHEMA esquema ] } [AUTHID { CURRENT_USER | DEFINER }]
{ USING {BFILE ( directorio , fichero ) 
        | {CLOB | BLOB | BFILE} subconsulta } 
|  AS texto JAVA }

ALTER JAVA SOURCE identificador_objeto COMPILE

 SOURCE Se carga un .java. Se ha de indicar el nombre de la clase.


 RESOURCE Se carga un .dat. Se ha de indicar el nombre de la clase.
 CLASS Se carga un .class. Parecido a loadjava.
 SCHEMA Indicamos en que esquema queremos crear el objeto.
 AUTHID Indicamos el propietario del objeto
 USING Indicamos como conseguimos la clase, fuente o recurso.
 AS Para introducir código java sin usar ficheros externos.

iv. JDBC
(wikipedia)JDBC es el acrónimo de Java Database Connectivity, un API que permite la
ejecución de operaciones sobre bases de datos desde Java, independientemente del
sistema de operación donde se ejecute o de la base de datos a la cual se accede
utilizando el SQL de la base de datos que se utilice.
El API JDBC se presenta como una colección de interfaces Java y métodos de gestión
de manejadores de conexión hacia cada modelo específico de base de datos. Un
manejador de conexiones hacia un modelo de base de datos en particular es un
conjunto de clases que implementan las interfaces Java y que utilizan los métodos de
registro para declarar los tipos de localizadores a base de datos (URL) que pueden
manejar. Para utilizar una base de datos particular, el usuario ejecuta su programa
junto con la librería de conexión apropiada al modelo de su base de datos, y accede a
ella estableciendo una conexión, para ello provee en localizador a la base de datos y
los parámetros de conexión específicos. A partir de allí puede realizar cualquier tipo de
tareas con la base de datos a las que tenga permiso: consultas, actualizaciones,
creado modificado y borrado de tablas, ejecución de procedimientos almacenados en
la base de datos, etc.

16 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Tipos JDBC:
 Bridge ( tipo 1 ) JDBC-ODBC tecnología de puente. Una mezcla de código
Java y software dependiente del sistema operativo, con el que JDBC accede a
una base de datos mediante ODBC.
 Native ( tipo 2 ) Ejecutables dependientes del sistema operativo y Java. Una
mezcla de código Java y software dependiente del sistema operativo con el
que JDBC accede a la base de datos a través de código propietario del
proveedor de la base de datos.
 Network (tipo 3 ) Middleware de Red y Java. Una mezcla de código Java y
código basado en un servidor donde el JDBC accede a la base de datos a
través de un middleware.
 Thin ( tipo 4 ) 100% Java. Un controlador Java puro que no requiere de código
dependiente del sistema operativo, lo que hace al controlador 100% portable.
El controlador Java depende de la base de datos a la cual queremos acceder.

En ORACLE nos encontramos con los siguientes terminos:


 Thin Driver: Es un controlador 100% de Java para el uso del lado del cliente
sin una instalación de Oracle, particularmente con los applet. Se usan los jar
ojdbc.jar y classes12.jar. Es el recomendado por la portabilidad.
 OCI Driver: Para el uso del lado del cliente con una instalación de Oracle. Se
usa el InstantClient de ORACLE, o las DLL (.so en LINUX/UNIX) instaladas por
los clientes y entornos de desarrollo de ORACLE.

Un ejemplo:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.SQLException;

public class JdbcTest {
    public static void main (String args []) throws SQLException {
        // Cargar Oracle driver
        DriverManager.registerDriver (new oracle.jdbc.OracleDriver());
        // Conectar a oracle
        Connection conn = DriverManager.getConnection
        ("jdbc:oracle:thin:@ host:puerto:sid","usuario", "password");
        // Cargar empleados
        Statement stmt = conn.createStatement ();
        ResultSet rset = stmt.executeQuery ("SELECT ename FROM emp");
        // Recorres y mostrar resultados
        while (rset.next ())
        System.out.println (rset.getString (1));
        //cerrar recordset, statement  y conexion
        rset.close();
        stmt.close();
        conn.close();
    }
}

17 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

v. SQLJ
(wikipedia)SQLJ es un estándard ISO (ISO/IEC 9075-10) para embeber sentencias
SQL en programas de Java. Al contrario que JDBC, SQLJ no es una API sino una
extensión del lenguaje. Así, los programas SQLJ deben ejecutarse a través de un
preprocesador (el traductor SQLJ) antes de que puedan ser compilados.

SQLJ tiene varias ventajas sobre JDBC:


 Los programas SQLJ son más fáciles de escribir y de mantener. Además
tienden a ser más cortos que los programas JDBC equivalentes.
 Es más eficiente que JDBC dado que las sentencias SQL son parseadas y los
caminos de acceso son optimizados en tiempo de compilación en lugar de en
tiempo de ejecución.
 Suministra mejor control de autorización: La Autorización puede ser concedida
a los programas en lugar de a los usuarios.
 Los problemas de rendimiento potenciales, tales como las consultas
ineficientes debido a un mal camino de acceso, pueden ser identificados en
tiempo de desarrollo.

Hay varias desventajas:


 SQLJ requiere un paso de preprocesamiento.
 Muchos IDEs no proporcionan soporte SQLJ.
 No hay soporte de SQLJ para la mayoría de frameworks de persistencia
comunes, tales como Hibernate.

18 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Un ejemplo:
import sqlj.runtime.*;
import sqlj.runtime.ref.*;
import java.sql.*;

#sql iterator TabIter (String);
public class SQLJTst {
  public static void main(String[] args) {
    Connection c = null;
    try {
      // Cargar Oracle driver
      DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
      c = DriverManager.getConnection("jdbc:oracle:thin:@host:puerto:sid", 
                                      "usuario", "passwdord");
      System.out.println("Conectando a Oracle...");
      DefaultContext.setDefaultContext( new DefaultContext(c));
      //Cargar empleados
      TabIter tabIter;
      #sql tabIter = { select ename from emp };
      // Recorres y mostrar resultados
      while (true) {
        String dBTabName = null;
        #sql { fetch :tabIter into :dBTabName};
        if ( tabIter.endFetch() ) break;
        System.out.println("Name: " + dBTabName);
      }
      //cerrar recordset, statement  y conexion
      #sql { commit work };
      #sql { rollback work };
      c.close();
      System.out.println("Desconectando...");
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }
}

19 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

2. Instalación de Oracle Developer Suite 10g


(10.1.2.0.2) para Windows.
La instalación de Oracle Developer Suite 10g es relativamente fácil.
Consta de 2 discos, en el primero nos aparece lo siguiente:

Figura 1

Donde “setup.exe”, es el Oracle Universal Installer, y es la aplicación que


debemos de ejecutar.
En el segundo disco sólo aparece el directorio “stage”.
NOTA: El nombre del recurso (o carpeta) donde se encuentran los discos, no es
recomendable que tenga espacios en blanco. Además, no se debe de guardar
“profundamente” en la jerarquía de directorios. (Cosas de JAVA)
Al ejecutar “setup.exe”, lo primero que realiza es una comprobación de los requisitos
(Figura 3). Por tanto, antes de que nos de error, comprobamos los siguientes puntos
1. Versión del sistema, que debe de ser la 5.0, 5.1 o 5.2. Para
comprobarlo, se debe de ejecutar el comando “VER“, en una consola
de MS-DOS.
2. Monitor, que debe de soportar 256 colores. Para comprobarlo,
Propiedades de PantallaConfiguración.
3. Espacio de intercambio (tamaño del archivo de paginación), que debe
de ser mayor que 1535 Mb. Para comprobarlo, Propiedades del
SistemaOpciones AvanzadasConfiguración(de la parte de
Rendimiento)Opciones AvanzadasCambiar (de la parte de
Memoria Virtual), y nos sale la siguiente pantalla:

Figura 2

20 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

4. Cambiamos el tamaño máximo (si hace falta) a un valor superior a


1535 Mb, y damos a Establecer.
5. Espacio temporal, que debe de ser superior a 150 Mb. Espacio de
disco duro donde esté ubicado el directorio “temp”

Después de las comprobaciones, nos da la bienvenida. Pinchamos en Siguiente

Figura 3

21 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

En la Figura 4 indicamos la ruta de Origen de los productos a instalar (No hace falta
cambiarlo), y el Destino donde se instala el producto. El Nombre es una descripción
del HOME de instalación, que utiliza el Oracle Universal Installer para distinguir entre
los distintos productos instalados en el equipo. Como es una instalación nueva, le
ponemos una nueva descripción.

Figura 4

22 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

En la Figura 5 nos pregunta que tipo de instalación deseamos hacer. Podemos escoger
las siguientes instalaciones:
1. Desarrollo J2EE. Esta opción nos instala el JDeveloper
principalmente. Ocupa aproximadamente 800 Mb.
2. Terminar Esta opción nos instala los productos JDeveloper, Forms
Reports y Designer (Toda la suite). Ocupa aproximadamente 1250
Mb.

Escogemos la opción Terminar y pulsamos Siguiente.

Figura 5

23 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

En la Figura 6 nos pregunta el servidor del correo saliente para la distribución de los
reports vía email.

Figura 6

24 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

En la Figura 7 nos muestra un resumen de los productos que nos va a instalar. Pulsamos
Instalar, y nos aparecerá la Figura 8.

Figura 7

25 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Figura 8
Puede ocurrir un error si la longitud del PATH es superior a 1023 caracteres. Si da
dicho error, modificar el PATH del sistema, y Reintentar la instalación.

Figura 9

En la Figura 10 nos
muestra la
ejecución del
asistente del
Net8, lo dejamos
que acabe, ya
que después
pondremos los
ficheros
tnsnames.ora y
sqlnet.ora
adecuados

26 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Figura 10

27 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

En la Figura 11 nos indica que ya ha acabado la instalación. Pulsamos Salir.

Figura 11
Recomendaciones
 No se pueden usar nombres de directorios con espacios en blanco para las
fuentes (Cosas de JAVA).
 Las páginas previas que llaman a los servlets de java se guardan en
C:\WINDOWS\Temp\*.Nhtm.(9i) Hay que tener cuidado con ellas, ya que se
guarda información sensible, referente a usuario y password.
 No se pueden usar rutas absolutas (C:\....) en los enlaces con las librerías, sólo
UNC o NetBIOS (\\servidor\....).

28 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

3. Forms Builder. Diferencias entre las versiones 6i y


10g.
a. Diferencias en el Navegador de Objetos:
Se invoca con F3 en las dos versiones.
6i (Navegador de Objetos)

10g (Navegador de Objetos)

29 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

El comportamiento de los menús es distinto. En la 10g aparecerá siempre las mismas


opciones (aunque dentro de ellas se activarán las opciones adecuadas) y en la 6i
aparecen las opciones según nos movamos por el Editor de Diseño, el Navegador
de Objetos, etc.
En la 10g aparece una barra de herramientas fija, parecida a la barra de herramientas
de la izquierda del Navegador de Objetos de la 6i.

b. Diferencias en el Editor de Informes:


Se invoca con F2 en las dos versiones.
6i (Editor de informes):

10g (Editor de informes):

30 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Las diferencias son mínimas en el entorno visual. Solo destacar, que el la caja de
herramientas de la 10g no encontraremos ninguna referencia a objetos OCX y OLE.

c. Diferencias en las Propiedades:


Se invoca con F4 en las dos versiones.
6i (Propiedades):

10i (Propiedades):

Las diferencias son el los iconos que se utilizan, pero son exactamente iguales en su
funcionalidad.

31 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

d. Propiedades que cambian de 6i a 10g:


Atributo de 6i Ámbito Efecto en 10g
Atributo lógico de modo Elementos, No migrado
carácter lienzos, etc
Tipo de comando Elementos Cambian los valores a escoger
de Menú solamente a PL/SQL, nulo ó menú
+Modo carácter (Listado en Bloques No migrado
menú de bloques de datos
y descripción del bloque de
datos)
Longitud fija Elementos No migrado. Usar las mascaras o
controlarlo por código
Descripción de la Ayuda Elementos No migrado
de Menú
Tipo de lista LOVs Obsoleto, no usar
Origen de Menú Formulario No migrado. Solo se permite menús con
origen en un fichero
Modo de compatibilidad de Formulario No migrado
ejecución
Estilo de disparador Disparadores Obsoleto, solo se permite PL/SQL
Blanco sobre negro Elementos, No migrado
lienzos, etc

32 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

e. Diferencias en las Paquetes incorporados,


constantes y disparadores:
Hay muchos procedimientos, funciones, constantes, paquetes, etc. que no se han
migrado o han cambiador su función.

Procedimientos y funciones:
APPLICATION_MENU No migrado o reemplazado funcionalidad
APPLICATION_PARAMETER No migrado o reemplazado funcionalidad
(Usar :GLOBAL)
BACKGROUND_MENU<N> No migrado o reemplazado funcionalidad
DEBUG_MODE No migrado o reemplazado funcionalidad
DISABLE_ITEM Usar SET_MENU_ITEM_PROPERTY()
ENABLE_ITEM Usar SET_MENU_ITEM_PROPERTY()
EXIT_MENU No migrado o reemplazado funcionalidad
HIDE_MENU No migrado o reemplazado funcionalidad
ITEM_ENABLED Usar
GET_MENU_ITEM_PROPERTY(<name>,
ENABLED). En futuras versiones no se
migrará
MAIN_MENU No migrado o reemplazado funcionalidad
MENU_CLEAR_FIELD Usar CLEAR_ITEM
MENU_FAILURE Usar FORM_FAILURE flag.
MENU_HELP No migrado o reemplazado funcionalidad
MENU_MESSAGE Usar MESSAGE
MENU_NEXT_FIELD Usar NEXT_ITEM
MENU_PARAMETER No migrado o reemplazado funcionalidad
(Usar :GLOBAL)
MENU_PREVIOUS_FIELD Usar PREVIOUS_ITEM
MENU_REDISPLAY No migrado o reemplazado funcionalidad
MENU_SHOW_KEYS Usar SHOW_KEYS
MENU_SUCCESS Usar FORM_SUCCESS flag
NEW_APPLICATION No migrado o reemplazado funcionalidad
NEW_USER Usar LOGOUT o LOGON
NEXT_MENU_ITEM No migrado o reemplazado funcionalidad
OS_COMMAND Usar HOST
OS_COMMAND1 Usar HOST
PREVIOUS_MENU No migrado o reemplazado funcionalidad
PREVIOUS_MENU_ITEM No migrado o reemplazado funcionalidad
QUERY_PARAMETER No migrado o reemplazado funcionalidad
(Usar :GLOBAL)
SET_INPUT_FOCUS No migrado o reemplazado funcionalidad
SHOW_BACKGROUND_MENU No migrado o reemplazado funcionalidad
SHOW_MENU No migrado o reemplazado funcionalidad
TERMINATE No migrado o reemplazado funcionalidad
(Usar :GLOBAL)
WHERE_DISPLAY No migrado o reemplazado funcionalidad
BLOCK_MENU No migrado o reemplazado funcionalidad
(KEY-MENU)
BREAK Migrar a DEBUG.SUSPEND
CALL Usar CALL_FORM
CHANGE_ALERT_MESSAGE Usar
SET_ALERT_PROPERTY(...,ALERT_MESSA

33 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

GE_TEXT,..);
DISPATCH_EVENT No migrado o reemplazado funcionalidad
(Usados en OCX)
(FORMS_OLE.)ACTIVATE_SERVER No migrado o reemplazado funcionalidad
(FORMS_OLE.)CLOSE_SERVER (Usados en OCX)
(FORMS_OLE.)EXEC_VERB
(FORMS_OLE.)FIND_OLE_VERB
(FORMS_OLE.)GET_INTERFACE_POINTER
(FORMS_OLE.)GET_VERB_COUNT
(FORMS_OLE.)GET_VERB_NAME
(FORMS_OLE.)INITIALIZE_CONTAINER
(FORMS_OLE.)SERVER_ACTIVE
MACRO No migrado o reemplazado funcionalidad
OHOST Usar HOST
PLAY_SOUND No migrado o reemplazado funcionalidad
READ_SOUND_FILE (Sonido)
WRITE_SOUND_FILE
ROLLBACK_FORM Usar CLEAR_FORM(NO_COMMIT,FULL_
ROLLBACK_NR ROLLBACK)
ROLLBACK_RL
ROLLBACK_SV
RUN_PRODUCT Valido únicamente para integrar con Oracle
Graphics,
use RUN_REPORT_OBJECT o
WEB.SHOW_DOCUMENT para Oracle
Reports. Para otros usos dará un error en
tiempo de ejecución

34 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Paquetes enteros que no se migran o cambian:


VBX No migrado (VBX)
FIRE_EVENT
GET_PROPERTY
GET_VALUE_PROPERTY
INVOKE_METHOD
SET_PROPERTY
SET_VALUE_PROPERTY
DEBUG No migrado o reemplazado funcionalidad.
BREAK Usar DEBUG.ATTACH o DEBUG.SUSPEND
GETC
GETD
GETI
GETN
INTERPRET
SETC
SETD
SETI
SETN
SUSPEND
PECS No migrado.
ADD_CLASS Usar Forms Trace u Oracle Trace. Mirar
ADD_EVENT manual A92175-01 para más detalles
COLLECTOR
DISABLE_CLASS
ENABLE_CLASS
END_EVENT
POINT_EVENT
START_EVENT

35 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Nuevos paquetes en la 10g:


FBEAN

Constantes:
DATE_FORMAT_COMPATIBILITY mode Usado por GET_APPLICATION y SET_
APPLICATION. La constante es ignorada.
POPUPMENU_CUT_ITEM No migrado o reemplazado funcionalidad
POPUPMENU_COPY_ITEM (Usados en OCX)
POPUPMENU_DELOBJ_ITEM
POPUPMENU_INSOBJ_ITEM
POPUPMENU_LINKS_ITEM
POPUPMENU_OBJECT_ITEM
POPUPMENU_PASTE_ITEM
POPUPMENU_PASTESPEC_ITEM
SHOW_POPUPMENU
COMPRESSION_OFF No migrado o reemplazado funcionalidad
COMPRESSION_ON (Sonido)
HIGHEST_SOUND_QUALITY
HIGH_SOUND_QUALITY
LOW_SOUND_QUALITY
LOWEST_SOUND_QUALITY
MEDIUM_SOUND_QUALITY
MONOPHONIC
ORIGINAL_QUALITY
ORIGINAL_SETTING
SHOW_FAST_FORWARD_BUTTON
SHOW_PLAY_BUTTON
SHOW_RECORD_BUTTON
SHOW_REWIND_BUTTON
SHOW_SLIDER
SHOW_TIME_INDICATOR
SHOW_VOLUME_CONTROL
STEREOPHONIC

Síntaxis
NAME_IN() Usar & para las referencias indirectas

Parámetros predefinidos de los menús con problemas en 10g


:UN GET_APPLICATION_PROPERTY(USERNAME)
:PW GET_APPLICATION_PROPERTY(PASSWORD)
:LN GET_APPLICATION_PROPERTY(USER_NLS_LANG)
:AD GET_FORM_PROPERTY(NAME_IN('SYSTEM.CURRENT_ FORM'),FILE_NAME)
:SO :SYSTEM.TRIGGER_MENUOPTION (Nueva en Developer 9i/10g)
:TT No migrado o reemplazado funcionalidad

36 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Listado de disparadores (triggers) con problemas en 10g


ON-DISPATCH-EVENT No migrado o reemplazado funcionalidad (Usados
en OCX)
WHEN-CLEAR-BLOCK Sólo se pueden usar a nivel de formulario y de
WHEN-CREATE-RECORD bloque, nunca a nivel de elemento
WHEN-DATABASE-RECORD
WHEN-NEW-RECORD-INSTANCE
WHEN-REMOVE-RECORD
WHEN-NEW-FORM-INSTANCE Sólo se pueden usar a nivel de formulario, nunca a
nivel de elemento y de bloque.
WHEN-MOUSE-MOVE Ignorados en entornos Web
WHEN-MOUSE-ENTER
WHEN-MOUSE-LEAVE

f. Diferencias en el Editor PL/SQL:


Se invoca con F11 en las dos versiones.
6i (Editor PL/SQL):

10g (Editor PL/SQL):

En vez de botones, usa iconos, añadiendo los de sangría. Se ha traducido Menu item
code por Código de Opción de Menú. Se han eliminado los botones de Nuevo… y
Borrar.

37 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

g. Procedimientos
Si se usa el asistente de bloque de datos, nos da a elegir entre 2 opciones:

La opción Procedimiento Almacenado, nos permite manejar la información del bloque


de datos a partir de procedimientos almacenados, para consulta, inserción, actualizar,
suprimir y bloqueo (obligatorio en el caso de actualizar y suprimir).

Para este ejemplo he creado las tablas:


CREATE TABLE PLAN2004 (ID_EXPEDIENTE NUMBER(5) NOT NULL,
CONCEPTO VARCHAR2(100), BENEFICIARIO VARCHAR2(9),
FECHA_RESOLUCION DATE, FECHA_ALTA DATE,
USUARIO VARCHAR2(10), BORRADO CHAR(1) DEFAULT 'N',
CONSTRAINT "CLAVE_PLAN2004" PRIMARY KEY("ID_EXPEDIENTE"));
Y lo mismo para plan2005 y plan2006
Y para los bloqueos:
CREATE TABLE BLOQUEOS (BLOQUEO DATE DEFAULT sysdate,
ID_EXPEDIENTE NUMBER(5), COD_PLAN NUMBER(4));
Y manejo el siguiente paquete:
CREATE OR REPLACE PACKAGE "PROCEDIMIENTOS" AS
/**Registro para la creación de un tipo tabla necesario para los
procedimientos de consulta, bloqueo y borrado.
**/
type parametros_rec is RECORD
(expediente plan2004.id_expediente%type);

-- Ref Cursor para el procedimiento de consulta


type rc_plan is REF CURSOR return plan2004%rowtype;

--La tabla para los parametros de consulta y bloqueo


type t_tablaborrar is table of parametros_rec
index by binary_integer;

38 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

procedure consulta(refcursor in out rc_plan,


plan_anual in number);
procedure borrar (expediente in plan2004.id_expediente%type,
parametros in t_tablaborrar);
procedure bloquear (expediente in plan2004.id_expediente%type,
parametros in t_tablaborrar);
END;

CREATE OR REPLACE PACKAGE BODY "PROCEDIMIENTOS" AS


procedure consulta(refcursor in out rc_plan,
plan_anual in number) is
temporal rc_plan;
begin
if plan_anual = 2004 then
open temporal for select id_expediente
||plan_anual as "id_expediente" ,concepto,
beneficiario, fecha_resolucion, fecha_alta, usuario,
borrado from plan2004 where borrado ='N';
elsif plan_anual = 2005 then
open temporal for select id_expediente
||plan_anual as "id_expediente" ,concepto,
beneficiario, fecha_resolucion, fecha_alta, usuario,
borrado from plan2005 where borrado ='N';
elsif plan_anual = 2006 then
open temporal for select id_expediente
||plan_anual as "id_expediente" ,concepto,
beneficiario, fecha_resolucion, fecha_alta, usuario,
borrado from plan2004 where borrado ='N';
end if;
refcursor := temporal;
end consulta;

39 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

procedure borrar (expediente in plan2004.id_expediente%type,


parametros in t_tablaborrar) is
c_expediente varchar2(10);
c_plan varchar2(4);
n_expediente number(10);
begin
c_expediente := to_char(expediente);
c_plan := substr(c_expediente,length(c_expediente)-3,4);
c_expediente := substr(c_expediente,1,length(c_expediente)-4);
n_expediente := to_number(c_expediente);
if c_plan = '2004' then
update plan2004 set borrado='S'
where id_expediente = n_expediente;
elsif c_plan = '2005' then
update plan2005 set borrado='S'
where id_expediente = n_expediente;
elsif c_plan = '2006' then
update plan2006 set borrado='S'
where id_expediente = n_expediente;
end if;
end borrar;

40 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

procedure bloquear (expediente in plan2004.id_expediente%type,


parametros in t_tablaborrar) is
c_expediente varchar2(5);
c_plan varchar2(4);
aux_id_expediente number;
consulta varchar2(200);
begin
c_expediente := to_char(expediente);
c_plan := substr(c_expediente,length(c_expediente)-3,4);
c_expediente := substr(c_expediente,1,length(c_expediente)-4);
insert into bloqueos (id_expediente,cod_plan)
values (to_number(c_expediente),to_number(c_plan));
end bloquear;
END;

A continuación, muestro las pantallas del asistente para poder usar los procedimientos
antes explicados:

41 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Los procedimientos que no son de consulta, el forms genera triggers para cada uno de
ellos. En este ejemplo, genera el triggers DELETE_ PROCEDURE y
LOCK_PROCEDURE. Estos triggers NO se han de modificar, ya que son
automáticamente generados por el Forms

42 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

h. Árbol jerárquico.
Los árboles jerárquicos (hierarchical tree) nos muestran información de forma
ordenada por niveles, parecido a una jerarquía de directorios.
Los árboles deben estar en bloques de una sola fila y un solo elemento.
Para este ejemplo he creado la tabla:
create table jerarquia
(identificador number(4),
nombre varchar2(15),
depende number(4));
Con los datos:
insert into jerarquia
select * from
(select deptno as identificador,
dname as nombre ,
0 as depende from dept
union
select empno as identificador ,
ename as nombre,
deptno as depende from emp);

El PL/SQL para poder rellenar el árbol jerárquico (en este ejemplo se ve como
rellenarlo de tres maneras) es (se crea en el disparador: WHEN-NEW-FORM-
INSTANCE):

declare
nododepartamento ftree.node;
nodoempleado ftree.node;
n_departamento number;
retorno_populate_group number;

cursor departamento is
select dname, deptno from dept
order by dname;

43 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

cursor empleados is
select ename from emp
where deptno = n_departamento
order by ename;
--la consulta base para el grupo de registros,
--como para el data query del árbol es:
--select -1, level, nombre, null ,depende
--from jerarquia
--start with depende = 0
--connect by prior identificador=depende
begin
--relleno de un árbol jerarquico
--usando programación
for r_departamento in departamento loop
nododepartamento := ftree.add_tree_node('bloque.arbol',
ftree.root_node, ftree.parent_offset, ftree.last_child,
ftree.leaf_node,r_departamento.dname, 'computer',
r_departamento.dname);

44 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

n_departamento := r_departamento.deptno;
for r_empleado in empleados loop
nodoempleado := ftree.add_tree_node('bloque.arbol',
nododepartamento, ftree.parent_offset,
ftree.last_child, ftree.leaf_node,
r_empleado.ename, null, r_empleado.ename);
end loop;
end loop;

--usando un grupo de registro


retorno_populate_group:=populate_group('registro_arbol');
ftree.set_tree_property('bloque1.arbol1', ftree.record_group,
'registro_arbol');

--usando el data query del árbol


ftree.populate_tree('bloque2.arbol2');
end;

Para añadir elementos al árbol se usa:


ftree.add_tree_node({‘nombre_árbol’|identificador_árbol},
nodo_nuevo_a_insertar FTREE.NODE, offset1 NUMBER,
offset2 NUMBER, estado NUMBER, etiqueta VARCHAR2,
icono VARCHAR2, valor VARCHAR2);

offset1 puede tomar los valores PARENT_OFFSET, ó SIBLING_OFFSET, indica si el


nodo se coloca a partir del padre, o del hermano.
offset2 pude tomar los valores:
Si offset1 es PARENT_OFFSET  -1 ó LAST_CHILD
Si offset1 es SIBLING_OFFSET  NEXT_NODE ó PREVIOUS_NODE
estado puede tomar los valores COLLAPSED_NODE, EXPANDED_NODE ó LEAF_NODE

Propiedades de nodo (Se pueden manejar con GET/SET_TREE_NODE)


 NODE_STATE (SET/GET) Estado del nodo.
 NODE_LABEL (SET/GET) Etiqueta del nodo.
 NODE_ICON (SET/GET) Nombre icono del nodo.
 NODE_VALUE (SET/GET) Valor del nodo.
Propiedades de árbol (Se pueden manejar con GET/SET_TREE_NODE)
 DATASOURCE (GET)
 RECORD_GROUP (SET/GET) Grupo de registros.
 QUERY_TEXT (SET/GET) Texto del DataQuery.
 NODE_COUNT (GET) Devuelve el número de elementos del árbol.
 SELECTION_COUNT (GET) Devuelve el número de elementos seleccionados
del árbol.
 ALLOW_EMPTY_BRANCHES (SET/GET) Permitir derivaciones vacías. Los
valores que puede tomar son: TRUE ó FALSE.
 ALLOW_MULTI-SELECT (GET) Permitir selección multiple.

45 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

i. JAVA en Forms Developer


Lo que se explica a continuación sirve para las versiones 10g y la 6i.

i. Entorno.
Versiones JAVA:
 En la 6i nos encontramos el problema de la versión de JAVA, ya que le hace
falta una versión superior a la 1.2.2, además, hay que tener cuidado con la DLL
de JDK symcjit.dll. El error que muestra en caso de no haber tenido en cuenta
las explicaciones anteriores es:

 En la 10g no nos encontramos problemas de versión. Exceptuando cuando


compilamos las clases, que es recomendable hacerlo con el javac que nos
proporciona el Developer.

Variable de entorno CLASSPATH: (ORACLE_HOME indica dónde está instalado el


Developer)
 En 10g
o ORACLE_HOME\forms\java\frmwebutil.jar;
o ORACLE_HOME\forms\java\frmall.jar;
 En 6i:
o ORACLE_HOME\FORMS60\java;
o ORACLE_HOME\TOOLS\COMMON60\JAVA\IMPORTER.JAR;
La ruta donde se encuentren las clases que se quieren usar con Developer, se han de
indicar en la variable de entorno CLASSPATH.
Dichas clases compiladas se deben de copiar después en ORACLE_HOME\forms\java,
para que el OAS del Developer los pueda usar.

Registro:
 En 6i hay que crear, si no lo están, los valores del tipo “valor de cadena
expandible”:
o FORMS60_JAVADIR = ORACLE_HOME\FORMS60\java;
o ORACLE_JDK = ORACLE_HOME\JDK;

46 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

ii. Usando JAVA en Developer.


JAVA se puede usar principalmente para 2 cosas, para mejorar un elemento del
formulario, o para incluir un Bean en un formulario. Por medio de los siguientes
ejemplos, se explica el uso de JAVA en Developer.

Mejorando un botón (Ejemplo Ayuda Developer)


Este ejemplo sólo modifica la apariencia del botón, lo redondea. Es muy sencillo.
Creamos una clase con el bloc de notas con el siguiente código:
import oracle.forms.ui.VButton;
//Heredamos de la clase VButton, que es la clase del botón
public class SingleButton extends VButton{
public SingleButton(){
//Se invoca al constructor base de la clase VButton
super();
//Llamamos a los métodos que redondean los bordes del botón
setLeftmost(true);
setRightmost(true);
}
}
La compilamos, usando el javac que nos proporciona Developer (para evitar
problemas con las versiones de JAVA)
La clase compilada la copiamos en ORACLE_HOME\forms\java\, que es la ruta que usa
el OMS del Developer para buscar las clases.
Indicamos en la propiedad “Clase de Implementación” de un botón, que use la clase
SingleButton, no se tiene que indicar la extensión .class.
Observar que en la clase SingleButton heredamos del objeto VButton

47 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Incluir un Bean en Developer (Ejemplo Ayuda Developer).


En este ejemplo, incluimos un Bean, y creamos unos procedimientos para ver como
comunicarnos con el Bean. El Bean que usaremos ya está creado, es un ejemplo que
viene con Beans Development Kit (BDK). El Bean muestra a Duke jugar con unos
frijoles.
Clase que carga un Bean en Developer:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import oracle.forms.properties.ID;
import oracle.forms.handler.IHandler;
import oracle.forms.ui.CustomEvent;
import oracle.forms.ui.VBean;
public class JugglerWrapper extends VBean implements MouseListener{
private Component mComp;
private IHandler mHandler;
//declaramos las propiedades que se pueden manejar con Developer
private static final ID
MOUSEPRESSED = ID.registerProperty("MousePressed");
private static final ID
MOUSEENTERED = ID.registerProperty("MouseEntered");
private static final ID
MOUSEEXITED = ID.registerProperty("MouseExited");
private static final ID
X_POS = ID.registerProperty("MouseX");
private static final ID
Y_POS = ID.registerProperty("MouseY");
private static final ID
ARATE = ID.registerProperty("AnimationRate");
private static final ID
STOP = ID.registerProperty("Parar");
private static final ID
START = ID.registerProperty("Arrancar");
private static final ID
SETRATE = ID.registerProperty("SetAnimationRate");
private static final ID
GETRATE = ID.registerProperty("GetAnimationRate");
public JugglerWrapper(){

48 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

//Se invoca al constructor base de la clase VBean


super();
try{
//Cargamos el Bean
ClassLoader cl = getClass().getClassLoader();
Object obj = Beans.instantiate(cl,
"sunw.demo.juggler.Juggler");
mComp = (Component) obj;
mComp.setVisible(true);
mComp.setEnabled(true);
add("Center", mComp);
if ( mComp instanceof Applet ){
Applet apl = (Applet) Beans.getInstanceOf(mComp,
Applet.class);
apl.start();
}
}catch ( Exception e ){//Control de errores}
}

49 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

public void init(IHandler handler){


super.init(handler);
mHandler = handler;
mComp.addMouseListener(this);
}

public void destroy(){


if ( mComp instanceof Applet ){
Applet apl = (Applet) Beans.getInstanceOf(mComp, Applet.class);
apl.stop();
apl.destroy();
}
}
//método para modificar el comportamiento del bean
public boolean setProperty(ID pid, Object value){
if ( pid == STOP ){
if ( ((Integer)value).intValue() == 1){
((sunw.demo.juggler.Juggler)mComp).stopJuggling();
}
return true;
} else
if ( pid == START ){
if ( ((Integer)value).intValue() == 1){
((sunw.demo.juggler.Juggler)mComp).startJuggling();
}
return true;
} else
if ( pid == SETRATE ){
((sunw.demo.juggler.Juggler)mComp)
.setAnimationRate(((Integer)value).intValue());
return true;
}
return super.setProperty(pid, value);
}
//Implementación del interfaz MouseListener
public void mouseClicked(MouseEvent event){ }

public void mouseEntered(MouseEvent event){


CustomEvent ce = new CustomEvent(mHandler, MOUSEENTERED);
dispatchCustomEvent(ce);
}

public void mouseExited(MouseEvent event){


CustomEvent ce = new CustomEvent(mHandler, MOUSEEXITED);
dispatchCustomEvent(ce);
}

public void mousePressed(MouseEvent event){


Integer xobj = new Integer(event.getX());
Integer yobj = new Integer(event.getY());
try{
mHandler.setProperty(Y_POS, yobj);
mHandler.setProperty(X_POS, xobj);
}catch (Exception e){ }
CustomEvent ce = new CustomEvent(mHandler, MOUSEPRESSED);
dispatchCustomEvent(ce);
}

50 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

public void mouseReleased(MouseEvent event){ }


}

Lo compilamos, copiamos la clase a ORACLE_HOME\forms\java\.


Creamos un área de Bean, e indicamos en la propiedad “Clase de Implementación”,
que use la clase JugglerWrapper
Observar que en la clase JugglerWrapper
 Definimos los atributos que podrán ser manejados por Developer:
private static final ID nombreInternoClase =
ID.registerProperty("NombreParaDeveloper");
 Cargamos el Bean.
 Lo inicializamos.
 Creamos los métodos setProperty y getProperty apropiados para
comunicar el bean con Developer.
 Si es necesario, controlamos los eventos que se producen en el Bean.

Procedimiento que captura los eventos que genera el Bean:


PROCEDURE Juggler_event_trap IS
ListaParametros ParamList;
TipoParametro Number;
NombreEvento VarChar2(20);
ValorParametro number(4);
XPos Number(4);
YPos Number(4);
Begin
ListaParametros :=
get_parameter_list(:SYSTEM.Custom_Item_Event_Parameters);
NombreEvento := :SYSTEM.Custom_Item_Event;
:nombre_evento := NombreEvento;
if (NombreEvento = 'MousePressed') then
get_parameter_attr(ListaParametros,'MouseX',
TipoParametro, ValorParametro);
XPos := ValorParametro;
get_parameter_attr(ListaParametros,'MouseY',
TipoParametro, ValorParametro);
YPos := ValorParametro;
message('Click en las coordenadas' ||
to_Char(XPos) || '/' || to_Char(YPos));
end if;
End;
Este procedimiento se llama cuando se produce el disparador WHEN-CUSTOM-ITEM-
EVENT del área de Bean

51 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Procedimiento que cambia propiedades del bean


PROCEDURE start_stop_bean IS
BotonControl Item;
EtiquetaBoton VarChar2(30);
Bean Item;
BEGIN
BotonControl := find_item('START_STOP_BTN');
if NOT id_null(BotonControl) then
EtiquetaBoton := get_item_property(BotonControl, LABEL);
Bean := find_item('JUGGLER_BEAN');
if NOT id_Null(Bean) then
if EtiquetaBoton = 'Arrancar Bean!' then
set_custom_property(Bean, ALL_ROWS, 'Arrancar', 1);
set_item_property (BotonControl, LABEL, 'Parar Bean!');
elsif EtiquetaBoton = 'Parar Bean!' then
set_custom_property(Bean, ALL_ROWS, 'Parar', 1);
set_item_property (BotonControl, LABEL,
'Arrancar Bean!');
end if;
end if;
end if;
END;

52 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Mejorando una caja de texto


En este otro ejemplo veremos otra manera de mejorar un elemento del formulario, en
este caso, una caja de texto a la cuál, validaremos si es texto, números, o cumple una
mascara de entrada. En tiempo de ejecución podemos indicar que tipo de validación
tiene.
package ejemplosCurso;

import oracle.forms.ui.*;
import oracle.forms.handler.IHandler;
import oracle.forms.properties.ID;
import oracle.forms.engine.*;
import java.awt.event.*;
import java.util.StringTokenizer;

public class KeyFilter extends VTextField


{

public final static ID KEYCODE =


ID.registerProperty("KEY_CODE");
public final static ID KEYCHAR =
ID.registerProperty("KEY_CHARACTER");
public final static ID KEYMODIFIER =
ID.registerProperty("KEY_MODIFIER");
public final static ID FILTERTYPE =
ID.registerProperty("FILTER_TYPE");
public final static ID CUSTOMFILTER =
ID.registerProperty("CUSTOM_FILTER");

public final static int ALPHA_FILTER = 0;


public final static int NUMERIC_FILTER = 1;
public final static int ALPHANUMERIC_FILTER = 2;
public final static int CUSTOM_FILTER = 3;
public final static int NO_FILTER = 4;

private String SavedKeyChar = null;


private char FilterChar = 0;
private int SavedKeyCode;
private String SavedModifier;
private int FilterState;
private String[] FilterArrays = new String[4];
private String[] FilterNames = new String[5];
private boolean CustomFilterSet = false;

public KeyFilter() {
super();
try {
jbInit();
}
catch (Exception e) {
e.printStackTrace();
}
}

53 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

private void jbInit() throws Exception {


// Set up the pre-defined filters
FilterState = NO_FILTER;
FilterArrays[ALPHA_FILTER] = new String
("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ");
FilterArrays[NUMERIC_FILTER] = new String ("1234567890.,");
FilterArrays[ALPHANUMERIC_FILTER] = new String
("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890.,");
FilterNames[ALPHA_FILTER] = new String("ALPHA");
FilterNames[NUMERIC_FILTER] = new String("NUMERIC");
FilterNames[ALPHANUMERIC_FILTER] = new String("ALPHANUMERIC");
FilterNames[CUSTOM_FILTER] = new String("CUSTOM");
FilterNames[NO_FILTER] = new String("NONE");

addKeyListener(new KeyPressAdapter());
}

public Object getProperty(ID pid)


{
if ( pid == KEYCODE )
{
return ""+ SavedKeyCode;
}
else if ( pid == KEYCHAR )
{
return "" + SavedKeyChar;
}
else if ( pid == KEYMODIFIER )
{
return SavedModifier;
}
if ( pid == FILTERTYPE )
{
return FilterNames[FilterState];
}
else if (pid == CUSTOMFILTER)
{
if (CustomFilterSet)
{
return FilterArrays[CUSTOM_FILTER];
}
else
{
return null;
}
}
else
{
return super.getProperty(pid);
}
}

public boolean setProperty(ID pid, Object value)


{
if ( pid == FILTERTYPE )
{
String PropValue = value.toString();

54 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

FilterState = 4;
for (int i = 0; i <= 3;i++)
{
if (PropValue.toUpperCase().compareTo(FilterNames[i]) == 0)
{
FilterState = i;
break;
}
}
return true;
}
else if (pid == CUSTOMFILTER)
{
if ((value.toString().equals("false")) && (value.hashCode() ==
1237))
{
System.out.println("Null custom Filter");
CustomFilterSet = false;
}
else
{
FilterArrays[CUSTOM_FILTER] = value.toString();
CustomFilterSet = true;
}
return true;
}
else
{
return super.setProperty(pid, value);
}
}

class KeyPressAdapter
extends KeyAdapter
{
public void keyPressed(KeyEvent e)
{
String ThisToken;
SavedKeyCode = e.getKeyCode();
StringTokenizer stMain = new
StringTokenizer(e.paramString(),",");
stMain.nextToken();
stMain.nextToken();
ThisToken = stMain.nextToken();
if (ThisToken.indexOf('=') > 0)
{
FilterChar = e.getKeyChar();
SavedKeyChar = "" + FilterChar;
if (FilterChar == 0) // If a modifier is pressed on it's own
{
SavedKeyChar = "{Modifier}";
}
}
else
{
FilterChar = 0;
SavedKeyChar = "{" + ThisToken + "}";

55 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

}
if (stMain.hasMoreTokens())
{
StringTokenizer stSub = new
StringTokenizer(stMain.nextToken(),"=");
stSub.nextToken();
SavedModifier = stSub.nextToken().toUpperCase();
}
else
{
SavedModifier = null;
}
}

public void keyTyped(KeyEvent e)


{
if ((FilterChar != 0) &&
(filterRequired(FilterState,FilterChar)))
{
e.setKeyChar(java.awt.event.KeyEvent.CHAR_UNDEFINED);
}
}

private boolean filterRequired(int FilterType, int KeyChar)


{
if (FilterType == NO_FILTER)
{
return false;
}
else
{
if ((FilterType == CUSTOM_FILTER) && (!CustomFilterSet))
{
return false;
}
else if (FilterArrays[FilterType].indexOf(KeyChar) == -1)
{
return true;
}
else
{
return false;
}
}
}
}
}

56 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Incluir un Bean en Developer II (Un reloj).


En este otro ejemplo veremos otra manera de crear un contenedor para incluir un
Bean en un Form. También veremos el código típico de un Bean.
// TickerAppletWrapper
package oracle.forms.demos; import oracle.forms.ui.*;
import oracle.forms.properties.*;
import oracle.forms.handler.*;
import java.awt.*;

public class TickerAppletWrapper extends VBean{


public static final ID START = ID.registerProperty("START");
public static final ID STOP = ID.registerProperty("STOP");
public static final ID XPOS = ID.registerProperty("XPOS");
public static final ID YPOS = ID.registerProperty("YPOS");
public static final ID FONT = ID.registerProperty("FONT");
public static final ID OUTERSIZE = ID.registerProperty("OUTERSIZE");
public static final ID BACKGROUND =
ID.registerProperty("BACKGROUND");
public static final ID FOREGROUND =
ID.registerProperty("FOREGROUND");
private TickerApplet ta = null;

public void init(IHandler handler){


super.init(handler);
System.out.println("init");
ta = new TickerApplet();
add(ta);
ta.start();
}

public void destroy(){


ta.stop();
}

public Object getProperty(ID id){


try{
if (id == FOREGROUND){
return ta.getForeground();
}
if (id == BACKGROUND){
return ta.getBackground();
}
if (id == FONT){
return ta.getFont();
}
return super.getProperty(id);
}catch (Exception e){
e.printStackTrace();
return null;
}
}
public boolean setProperty(ID id, Object value){
try{
if (id == START){
System.out.println(getClass().getName() + "ID:START");

57 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

ta.start();
return true;
}
if (id == STOP){
System.out.println(getClass().getName() + "ID:STOP");
ta.stop();
return true;
}
if (id == XPOS){
ta.setX(Integer.parseInt((String)value));
return true;
}
if (id == YPOS){
ta.setY(Integer.parseInt((String)value));
return true;
}
if (id == FOREGROUND){
ta.setForeground((Color)value);
return true;
}
if (id == BACKGROUND){
ta.setBackground((Color)value);
return true;
}
if (id == OUTERSIZE){
Point p = (Point)value;
System.out.println("OUTERSIZE:" + value.toString());
ta.setSize(new Dimension(p.x,p.y));
return super.setProperty(id,value);
}
if (id == FONT){
ta.setFont((Font)value);
return true;
}

return super.setProperty(id, value);


} catch (Exception e){
e.printStackTrace();
return false;
}
}
}

58 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Y el applet, o Bean es:


//TickerApplet
package oracle.forms.demos;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.text.*;
import oracle.ewt.lwAWT.*;
public class TickerApplet extends LWComponent implements Runnable{
private int x = 5;
private int y = 15;
private int swidth = 0;
private int sheight = 0;
private int height=25;
private int width=100;
private int fontSize = 16;
private Font font = new Font("Helvetica", Font.BOLD, fontSize);
private Color background = Color.black;
private Color foreground = Color.green;
private Image memImage = null;
private Graphics offScr = null;
private static String fullMessage = "TIME IS ... ";
private DateFormat df = DateFormat.getTimeInstance();
private Thread tickerThread = null;

public TickerApplet(){
initMouseDrag();
}

public void setFontSize(int fs){


this.fontSize = fs;
font = new Font("Helvetica", Font.BOLD, this.fontSize);
}
public int getFontSize(){
return this.fontSize;
}

public void setFont(Font f){


this.font = f;
}
public Font getFont(){
return font;
}

public void setBackground(Color background){


this.background = background;
}
public Color getBackground(){
return background;
}

public void setForeground(Color foreground){


this.foreground = foreground;
}
public Color getForeground(){
return foreground;

59 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

}
public void setX(int x){
this.x = x;
}
public int getX(){
return this.x;
}
public void setY(int y){
this.y = y;
}
public int getY(){
return this.y;
}

public void setSize(Dimension dim){


System.out.println(getClass().getName() +
":setSize(" + dim.toString() + ")");
super.setSize(dim);
this.width=dim.width;
this.height=dim.height;
calcOffsets();
repaint();
}

/*
public void init()
{
System.out.println(getClass().getName() + ": init()");
}
*/

public String getTimeString(){


df = DateFormat.getTimeInstance();
Date d = new Date();
return(df.format(d));
}

public void calcOffsets(){


String time = getTimeString();

// calculate the string attributes, height and width


FontMetrics fm = this.getFontMetrics(this.font);
swidth = fm.stringWidth(getTimeString());
sheight = fm.getHeight();

// set the X and Y positions


x = (this.width/2) - (swidth/2);
y = (this.height/2) + (sheight/2);

System.out.println(getClass().getName() +
"calcOffsets() " + time + " x=" + x + ", y=" + y);
}

public void start(){


System.out.println(getClass().getName() + ": start()");
tickerThread = new Thread(this);
tickerThread.start();

60 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

}
public void stop(){
System.out.println(getClass().getName() + ": stop()");
if (tickerThread != null) tickerThread.stop();
tickerThread = null;
}

public void paint(Graphics g){


g.setColor(background);
g.fillRect(0, 0, width, height);
g.setColor(foreground);
g.setFont(font);
g.drawString(fullMessage, x, y);
}

public void run(){


try{
System.out.println(getClass().getName() + ": run()");
while (true){
fullMessage = getTimeString();
memImage = this.createImage(width,height);
Graphics offScreenGraphic = memImage.getGraphics();
paint(offScreenGraphic);
Graphics onScreen = this.getGraphics();
onScreen.drawImage(memImage, 0, 0, this);
Thread.sleep(1000);
}
}catch (InterruptedException e){
e.printStackTrace();
}
}

public void initMouseDrag(){


{
this.addMouseMotionListener(new MouseMotionAdapter()
final int border = 5;
public void mouseDragged(MouseEvent me){
int mx = me.getPoint().x;
int my = me.getPoint().y;
x = mx;
y = my;
repaint();
}
});
}
}

61 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

j. ANEXO A. Herramientas de migración.


ORACLE nos proporciona herramientas para convertir formularios, módulos, menús,
etc. de la versión 6i a la 10g. se usa el comando
$ORACLE_HOME/BIN/frmplsqlconv.bat, si se ejecuta con mode=wizard, se ejecuta en
modo visual y aparecerá la siguiente pantalla:

Si se prefiere ejecutar en modo batch, en consola, y para ello se ha de indicar el


módulo, menú, etc. que se quiere convertir en el parámetro module=XXX.
Se puede crear un batch con la siguiente instrucción:
for %%ff in (%1) do call frmplsqlconv module=%%ff

Y se ejecuta pasándole como parámetro el módulo, o módulos.

La herramienta en la versión 9i cambia su nombre por ifplsqlconv90.bat, pero la forma


de ejecutarse es muy parecida a la que hemos visto.

62 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

4. Report Builder. Diferencias entre las versiones 6i y


10g
a. Diferencias en el Navegador de Objetos:
En primer lugar, en la 6i, se invoca con F3, en 10g es con F5
6i (Navegador de Objetos)

10g(Navegador de Objetos)

63 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

El Modelo de Diseño pasa a llamarse Disposición de Papel.


Desaparece el Visor Activo (Se podrá usar en el Editor de Informes), y aparece
Origen Web.
Desaparece Consultas SQL Externas
El comportamiento de los menús es distinto. En la 10g aparecerá siempre las mismas
opciones (aunque dentro de ellas se activarán las opciones adecuadas) y en la 6i
aparecen las opciones según nos movamos por el Editor de Informes, el Navegador
de Objetos, etc.
En la 10g aparece una barra de herramientas fija, parecida a la barra de herramientas
del Editor de Informes de la 6i.

Propiedades del módulo:


Las diferencias entre 6i y 10g son referentes a la Web. En la 10g se hace más
hincapié en las propiedades Web como Hojas de Estilo, Nombre de Clase CSS, etc.
Se añade una nueva familia de propiedades llamada Taxonomía de Documento, que
consiste en dar una clasificación al Report. Se añade una nueva propiedad a donde se
indica el idioma del Report

Parámetros del Sistema


En la 10g no aparecen BACKGROUND, CURRENCY, DECIMAL y THOUSANDS.
En la 10g aparecen los siguientes parámetros:
 COPIES  Número de copias a imprimir.
 DESFORMAT Puede ser:
o Formato de salida. Valores de ejemplo que puede tomar  PDF,
HTML, HTMLCSS, RTF, XML, SPREADSHEET, DELIMITED o
DELIMITEDDATA para bitmapped reports).

64 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

o Formato de salida impresa. Se usa cuando DESTYPE=FILE y


DESNAME=nombre_fichero. Si MODE=BITMAP, es el nombre de la
impresora. If MODE=CHARACTER, es el nombre del formato de fichero
de impresora(.prt file).
 DESNAME  Es el nombre del dispositivo de salida (nombre del fichero, e-
mail, etc).
 DESTYPE Es el tipo dispositivo de salida. Valores de ejemplo que puede
tomar  SCREEN, FILE, PRINTER, MAIL, SYSOUT, CACHE o LOCALFILE.
 MODE Modo en que se ejecuta el Report (CHARACTER o BITMAP)
 ORIENTATION Dirección en que se imprime el Report (LANDSCAPE
(paisaje), PORTRAIT (retrato), DEFAULT).
 PRINTJOB  Si se quiere que aparezca el dialogo de impresión (Yes o no).

Columnas de Variables Pendientes de Asignación, es en la 6i Columnas


Derivadas.

En la Disposición de Papel, en sus elementos que aparecen, tienen nuevas


propiedades como Accesibilidad y nuevos valores para Definiciones de la Web
(Valores de la Web en 10g). Se hace mucho hincapié en los estilos CSS.

65 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

b. Diferencias en el Editor de Diseño:


En primer lugar, en la 6i, se invoca con F2, en 10g es con F7.
6i (Modelo de Datos):

10g (Modelo de Datos):

Se diferencia en la barra de herramientas (El zoom, en 10g, se encuentra en


VerZoom), en los nuevos orígenes de datos que incorpora 10g. y en la opción de
Origen Web

66 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

6i (Modelo de Diseño):

10i (Modelo de Diseño):

Se diferencia en la barra de herramientas, en los elementos resaltados en rojo, y en la


forma de insertar objetos, que se encuentra en Insertar…

67 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

6i (Pantalla de Parámetros):

10i (Pantalla de Parámetros):

Apenas hay diferencia entre versiones.

68 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

c. Orígenes de datos:
El origen de datos es una función PL/SQL. Esta función devuelve una referencia
a un cursor. Es útil cuando se han de hacer cálculos según ciertas condiciones de la
consulta. Se separa un poco la lógica de negocio de la presentación. El siguiente
ejemplo está sacado de la ayuda del Developer. Este ejemplo se puede usar con
Developer 6i.
Se crea un paquete con el tipo del registro que devuelve la referencia a cursor, el REF
CURSOR, y una función que genera el REF CURSOR según unas reglas.
PACKAGE cv IS
type comp_rec is RECORD (
deptno number,
ename varchar(10),
compensation number
);
type comp_cv is REF CURSOR return comp_rec;
function emprefc(deptno1 number) return comp_cv;
END;

PACKAGE BODY cv IS
function emprefc(deptno1 number) return comp_cv
is
temp_cv cv.comp_cv;
begin
if deptno1 > 20 then
open temp_cv for
select deptno, ename,1.25*(sal+nvl(comm,0)) compensation
from emp where deptno = deptno1;
else
open temp_cv for
select deptno, ename, 1.15*(sal+nvl(comm,0)) compensation
from emp where deptno = deptno1;
end if;
return temp_cv;
end;
END;

Esta función se crea al insertar un origen de datos PL/SQL. Lo que hace es usar la
función y REF_CURSOR definidos en los paquetes.

Function function_ref_cursor return cv.comp_cv is


temp_cv cv.comp_cv;
begin
temp_cv := cv.emprefc(:deptno);
return temp_cv;
end;

Y nos devuelve un conjunto de registros para el informe.

69 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

El origen de datos es un fichero XML. No está muy lograda esta utilidad, ya que
falla si el árbol de objetos es profundo. Hay que afinar mucho en los DTD. Les faltan
muchas cosas.
La opción Validar Origen de Datos, si se activa indica que valide usando DOM, sino
valida usando SAX

El origen de datos es un fichero de texto plano. En Seleccionar el formato del


archivo de texto saldrá una lista definidita en un fichero de configuración llamado
ORACLE_HOME/reports/conf/textpds.conf, en este fichero es donde se indica cómo
es la estructura de los archivos de texto de los cuales se quiere mostrar un informe.

70 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

El origen de datos JDBC está pensado para conectarse con otros tipos de BDD
como SQLServer, Informix, DB2, etc. Los orígenes JDBC están especificados en un
fichero llamado ORACLE_HOME/reports/conf/jdbcpds.conf

OLAP es el acrónimo en inglés de procesamiento analítico en línea (online


analytical processing). Es una solución que suministra respuestas rápidas a consultas
a una base de datos complejas. Se usa en informes de negocios de ventas, marketing,
informes de dirección, minería de datos y áreas similares.

Las conexiones se guardan en ORACLE_HOME\reports\jlib\xrpdscon.ora, un fichero


con formato XML, un ejemplo:
<OLAP>
<services>
<con>
<description value="dsigca" /> <host value="141.10.0.14" />
<SID value="disgca" /> <port value="1543" />

71 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

</con>
</services>
</OLAP>

d. Diferencias en las Propiedades:


Se invoca con F4 en las dos versiones
6i (Propiedades):

10i (Propiedades):

Apenas hay diferencia entre versiones.

72 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

e. Plantillas.
Una plantilla es un objeto que define unas características comunes a un conjunto de
informes. Se guardan con la extensión .tdf. Son fáciles de crear y usar.
Las características que podemos modificar son:
 En el Modelo de Datos:
o Parámetros del sistema. Modificar
o Parámetros del usuario. Crear
 En la Disposición de Papel:
o Cuerpo:
 Valores por defecto: (Color, ubicación, justificación, etc.)
 Marcos.
 Etiquetas/Cabeceras del Campo.
 Campos.
 Etiquetas de Resumen.
 Resúmenes.
 Sustituir Según el modelo de informe que elijamos, se usará una
plantilla u otra (tabular, agrupar a la izquierda, carta, etc.)
o Margen Imágenes, rótulos, etc. de los márgenes.

73 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Para poder editar la plantilla de forma visual, se usa el Editor de Plantillas, al cual se
accede a través de Herramientas Editor de Plantillas o doble clic sobre
Disposición de Papel
Es bastante simple de usar.

74 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

75 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

f. JSP con Developer Report 10g.


Lo más novedoso de la herramienta de generación de Reports es el Origen Web, es
decir, el uso de JSP y HTML para la creación de reports.
Para este cometido se nos proporciona una biblioteca de etiquetas llamado
reports_tld.jar, que posteriormente explicaremos. Con esta biblioteca, el uso de JSP se
facilita, ya que divide la lógica del negocio (la fuente de datos) de la presentación
(diseño Web).
Las modificaciones que se realicen en el Origen Web, solo serán visibles cuando se
ejecute en diseño Web.

i. Conceptos Básicos.
JSP
La tecnología JSP, o de Java Server Pages, es una tecnología Java que permite a los
programadores generar dinámicamente HTML, XML o algún otro tipo de página Web.
Esta tecnología permite al código Java y a algunas acciones predefinidas ser
embebidas en el contenido estático. En las jsp, se escribe el texto que va a ser
devuelto en la salida (normalmente código HTML) incluyendo código java dentro de él
para poder modificar o generar contenido dinámicamente. El código java se incluye
dentro de las marcas de etiqueta <% y %>.
En una posterior especificación, se incluyeron taglib; esto es, la posibilidad de definir
etiquetas nuevas que ejecuten código de clases java.
La principal ventaja de JSP frente a otros lenguajes es que permite integrarse con
clases Java (.class) lo que permite separar en niveles las aplicaciones Web,
almacenando en clases java las partes que consumen más recursos así como las que
requieren más seguridad, y dejando la parte encargada de formatear el documento
html en el archivo jsp. (wikipedia)

Ejecución de un JSP
La primera vez que se realiza una petición de una página JSP, el contenedor Web
convierte el fichero JSP en un servlet que pueda responder a la petición HTTP. En
primer lugar traduce la página JSP en un fichero fuente Java que contiene la definición
de una clase servlet. En segundo lugar el contenedor Web compila el código fuente del
servlet en una clase Java (.class). El bytecode de esta clase Java se carga en la JVM
del contenedor Web utilizando un cargador de clases. En el tercer paso, el contenedor
Web crea una instancia de la clase servlet y lleva a cabo la fase de inicialización del
ciclo de vida invocando al método especial jspInit. Finalmente, el contenedor Web
puede invocar el método _jspService de la página JSP convertida, de modo que pueda
servir las peticiones HTTP del cliente.

Marcas de etiqueta
Dentro de las marcas <% y %>, nos podemos encontrar con:
 <%-- comentario --%> Comentarios JSP.
 <%@ directiva %> Directivas JSP.
 <%! declaración %> Declaración de variables o funciones.
 <% código %> Scriptlet. Java que deseamos ejecutar.
 <%= expresión %> Valor de expresión JAVA que queremos incluir en la página
Web.

76 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Directivas JSP
La directiva page nos permite definir uno o más de los siguientes atributos:
 import="package.class" o
import="package.class1,...,package.classN". Esto nos permite
especificar los paquetes que deberían ser importados. Por ejemplo:
<%@ page import="java.util.*" %>
El atributo import es el único que puede aparecer múltiples veces.
 contentType="MIME-Type" o contentType="MIME-Type;
charset=Character-Set" Esto especifica el tipo MIME de la salida. El valor
por defecto es text/html. Por ejemplo, la directiva:
<%@ page contentType="text/plain" %>
tiene el mismo valor que el scriptlet
<% response.setContentType("text/plain");%>
 session="true|false". Un valor de true (por defecto) indica que la variable
predefinida session (del tipo HttpSession) debería unirse a la sesión existente
si existe una, si no existe se debería crear una nueva sesión para unirla. Un
valor de false indica que no se usarán sesiones, y los intentos de acceder a la
variable session resultarán en errores en el momento en que la página JSP sea
traducida a un servlet
 buffer="sizekb|none". Esto especifica el tamaño del buffer para el
JspWriter out. El valor por defecto es específico del servidor, debería ser de al
menos 8kb.
 autoflush="true|false". Un valor de true (por defecto) indica que el
buffer debería descargase cuando esté lleno. Un valor de false, raramente
utilizado, indica que se debe lanzar una excepción cuando el buffer se
sobrecargue. Un valor de false es ilegal cuando usamos buffer="none".
 extends="package.class". Esto indica la superclase del servlet que se va
a generar. Debemos usarla con extrema precaución, ya el servidor podría
utilizar una superclase personalizada.
 info="message". Define un string que puede usarse para ser recuperado
mediante el método getServletInfo
 errorPage="url". Especifica una página JSP que se debería procesar si se
lanzará cualquier Throwable pero no fuera capturado en la página actual.
 isErrorPage="true|false". Indica si la página actual actúa o no como
página de error de otra página JSP. El valor por defecto es false.

La directiva include nos permite incluir ficheros en el momento en que la página JSP
es traducida a un servlet. Los ficheros pueden ser documentos estáticos como páginas
HTML, o documentos dinámicos como páginas JSP. Facilita la reutilización de un
documento en diversas páginas. Ejemplo:
<%@ include file="url relativa" %>

77 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

Taglib
Los taglib, son bibliotecas de etiquetas, cada etiqueta es un conjunto de scripts de
JAVA y HTML. Su utilidad radica en la reutilización de trozos comunes de JSP, como
por ejemplo accesos a bases de datos. Existe algo parecido como son los JavaBeans,
o los Entreprise Java Beans, que en general son códigos de JAVA compilados que se
utilizan dentro de un JSP. La diferencia entre los Beans y los Taglibs, es que estos
últimos pueden acceder a los objetos Request y Response, además de que los Beans
se utilizan para separar la capa de negocio de la presentación, es decir, que en un
Beans no debe de aparecer HTML, o código para representar información.
Los Taglibs se guardan con la extensión .tld.
Para poder utilizar las etiquetas definidas en un taglib, se usa la directiva siguiente:
<%@ taglib uri="/WEB-INF/lib/reports_tld.jar" prefix="rw" %>

Donde el prefix se usa para indicar que la etiqueta es del taglib indicado, como
veremos a continuación. Esto es algo parecido a los espacios de nombres del XML
Dentro de la página JSP, para poder usar las etiquetas del taglib:
<rw:style >
texto que encierre la etiqueta, o más etiquetas
</rw:style>

ii. reports_tld.jar
Report Builder nos proporciona el taglib reports_tld.jar.
Las etiquetas que podemos usar son:
 dataArea Indica el lugar donde el asistente de informes incluye los datos del
report. Se puede usar en conjunción con style.
<rw:dataArea id="identificador" >
[tag body]
</rw:dataArea>
 field Inserta un valor de un elemento del modelo de datos.
<rw:field id="identificador" src="nombre del objeto"
[breakLevel="Nivel de ruptura (Matrices)"]
[breakValue="valor de rotura (Matrices)"]
[nullValue="valor a mostrar en caso de nulo"]
[containsHtml="yes|true si contiene el valor código HTML"]
[formatMask="formato de mascara"]
[formatTrigger="función de formato(ver srw)"]
[urlEncode=" yes|true si convierte html a entidades (&lt)"] >
[tag body]
</rw:field>
 foreach Realiza el bucle en el cual se mostrará los datos de un grupo
<rw:foreach id="identificador" src="nombre del grupo"
[startRow="fila de inicio"] [endRow="fila última"]
[increment="salto"]>
[tag body]
</rw:foreach>
 getValue Crea un valor JAVA para manejarlo con scripst de JSP
<rw:getValue id=" identificador " src=" nombre del grupo "
[formatMask="formato de mascara"]>
[tag body]
</rw:getValue>

78 de 79
Nuevas funcionalidades para desarrolladores de
ORACLE 9i y 10g.

 graph Insertar un gráfico. Lo mejor es utilizar el asistente. El se encargará de


introducir las etiquetas XML y JSP necesarias
 headers Se usa en junto a id. Indica información de encabezado de la celda
<rw:headers id="identificador” src="atributos ID" />
 id Especifica información de encabezado
<rw:id id=" identificador " breakLevel="frequency"
[asArray="yes|no" />
 include
<rw:include id="layout_id" src="object_name"
[format="format"]>
[tag body]
</rw:include>
 objects Encapsula la definición de datos y salida en XML.
<rw:objects id="identificador">
[XML Report definitions]
</rw:objects>
 report Etiqueta raíz.
<rw:report id="nombre report" [parameters ="parámetros URL"]>
[tag body]
</rw:report>
 seq define una secuencia de valores, que se usarán con seqval
<rw:seq name="identificador" seq="valor,…" />
 seqval muestra el valor de la secuencia, y manipula la secuencia, es decir,
mueve el índice de la secuencia
<rw:seqval ref="indentificador de la secuencia"
op="operación" />
Operación puede ser:
o nextval devuelve el siguiente valor, y mueve el
índice de la secuencia al siguiente valor
o currval devuelve el valor actual de la secuencia
o reset mueve el índice al punto de arranque
o nextstart mueve el valor de arranque una posición
o start(N) mueve el valor de arranque N posiciones
o setCurrpos(N) mueve el índice N puestos
 style Indica la hoja de estilos del documento Web
<rw:style id="identificador">
Hojas de estilos
</rw:style>

79 de 79

Potrebbero piacerti anche