Spanish [B4XPages] jRDC2 + MySQL CRUD + Login

josejad

Expert
Licensed User
Longtime User
Hola a todos:


Por fin me he puesto a probar un poco con B4XPages, y he empezado a adaptar el ejemplo B4XPages + B4XDrawer
Creo que he visto algunos ejemplos con php + mysql para hacer login, etc... pero he visto pocos con jRDC2.
Los datos de la base de datos y la interfaz gráfica son bastante básicos, pero creo que suficiente para hacerse una idea.


¿Qué necesitas?
- Una base de datos mysql/mariadb. Puedes usar XAMPP, LARAGON o cualquier otro proyecto para configurarla. Adjunto un archivo sql que puedes importar para crear la base de datos y las tablas del ejemplo.
- B4J para crear el servidor jRDC2
- B4A 9.9+ que ya soporta B4XPages, aunque lo ideal es siempre actualizar a la última versión de B4A. (10.5 en el momento de escribir este post)

Pasos:
- Importar el archivo sql a tu base de datos. Puedes usar phpMyAdmin, HeidiSQL, etc…
- Configurar el servidor jRDC2. Para ello, abre el archivo jRDC2_B4J.zip, recuerda cambiar tu usuario y contraseña en el fichero config.properties
- Abre B4A, y en la clase jRDC2, cambia la constante rdcLink para que apunte al ordenador en el que estás ejecutando el servidor jRDC2 (B4J). (Puedes verlo con ipconfig en windows)
B4X:
Sub Class_Globals
    'CAMBIA ESTA IP PARA QUE APUNTE A TU SERVIDOR B4J
    Private const rdcLink As String = "http://192.168.1.131:8090/rdc"
End Sub
- Para añadir, editar, etc.. usaremos B4XPreferencesDialog. Puedes usar Form Builder para hacer los formularios. Es importante que los valores clave (key), se llamen igual que los campos de tu base de datos, ya que construiremos un mapa con los datos que recibimos de la base de datos, y se lo pasaremos a B4XPreferences, así que si los nombres coinciden, será mucho más fácil.

He comentado el código lo mejor que he podido.
Si veis cualquier error o sabéis alguna forma de mejorarlo, no dudéis en decirlo.
He intentado hacer el proyecto B4J también, pero nunca lo he usado y me da demasiados errores. Si alguno sabe hacerlo, sería genial para aprender (o en B4i)
EDITADO: He actualizado el proyecto, ahora funciona en B4J y B4A, no sé en B4i ya que no tengo una versión que soporte B4XPages.


La contraseña para todos los usuarios es: 1234 (almacenada en la base de datos como md5)

sql.Login = SELECT * FROM B4X.users WHERE `username` = ? AND `password` = md5(?)
sql.getEvents = SELECT * FROM B4X.events WHERE `month` = ? AND `id_user` = ?
sql.updateEvents = UPDATE B4X.events SET `month`=?,`event_type`=?,`description`=? WHERE `id` = ?
sql.deleteEvents = DELETE FROM B4X.events WHERE `id` = ?
sql.addEvents = INSERT INTO B4X.events(`id_user`, `month`, `event_type`, `description`, `value`) VALUES (?, ?, ?, ?, ?)


***** EDITADO *****
Puede ser de utilidad ver este hilo para tener más claro qué es un servidor jRDC2 y cómo distribuirlo:

saludos,
 

Attachments

  • sql.zip
    1.5 KB · Views: 584
  • jRDC_B4J.zip
    5.4 KB · Views: 597
  • Project.zip
    207.2 KB · Views: 625
Last edited:

josejad

Expert
Licensed User
Longtime User
Hola Oparra:

Muchas gracias¡¡

Pues en teoría se podría usar, (he intentado usar todo multiplataforma B4XViews, B4XPreferencesDialog, xCustomListView, ...). He intentado hacerlo funcionar en B4J pero no he dado con la tecla. A ver si tengo más tiempo y consigo echarlo a andar y lo subo.
Si alguno tenéis idea y hacéis las modificaciones necesarias para que funcione... encantado de que lo suba.

saludos,
 

josejad

Expert
Licensed User
Longtime User
Pues al final me está sorprendiendo que es más fácil pasar a B4J de lo que esperaba (aunque en realidad, es el objetivo de B4XPages)

Problemas que estoy encontrando:
- KVS.Initialize(File.DirInternal,"kvs"): miembro desconocido dirinternal.
solucionado using XUI.DefaultFolder

- PrefDialogEvents.Initialize(Root , "Events", 90%x, 300dip): miembro desconocido perxtocurrent
Solucionado cambiando 90%x a dip. PrefDialogEvents.Initialize(Root , "Events", 300dip, 300dip). Aún no estoy seguro de la mejor forma de solucionar esto.

- If GetDeviceLayoutValues.ApproximateScreenSize < 4.5 Then height = 310dip...
Solucionado añadiendo:
#if B4A
If GetDeviceLayoutValues.ApproximateScreenSize < 4.5 Then height = 310dip
#end if

Por ahora no funciona:
- No sale el + en la barra de títulos para añadir
- Las etiquetas para editar y borrar no funcionan

Sigo con ello

TIP: Se aprende un montón con el ejemplo multiplataforma de Erel: B4XPleroma client.

1612301663309.png
 

angel_

Well-Known Member
Licensed User
Longtime User
Yo le añadiría en B4XMainPage para copiar los archivos:

B4X:
#Region Shared Files
#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files"
'Ctrl + click to sync files: ide://run?file=%WINDIR%\System32\Robocopy.exe&args=..\..\Shared+Files&args=..\Files&FilesSync=True
#End Region

Para %x puedes utilizar algo así:

B4X:
Public MainForm As Form    'En Main

Main.MainForm.Width * 0.90 '90%x

Utilizo soluciones multiplataforma para todo lo que puedo como: BCToast
También prefiero utilizar: B4XFloatTextField (para EditText y TextField), B4XImageView, SwiftButton (no me gusta tanto)
Lo que puedo lo declaro como B4XView, por ejemplo, para label

Para el clic de los label utilizo esto (que es bastante feo) pero no he encontrado una solución mejor (estoy abierto a mejores opciones):
B4X:
#if b4a or b4i
Private Sub lblDelete_Click
#else if b4j
Private Sub lblDelete_MouseClicked (EventData As MouseEvent)
#end if
    'Código
End Sub
 

TILogistic

Expert
Licensed User
Longtime User
Use: DipToCurrent

PrefDialogEvents.Initialize(Root , "Events", 90%x, 300dip)

PrefDialogEvents.Initialize(Root, "Events", DipToCurrent(Root.Width * 0.90), DipToCurrent(300))

por lo que he visto no son muchos los cambios.

vamos que se puede!!!

???

Saludos.
 

josejad

Expert
Licensed User
Longtime User
Gracias a los dos por los consejos:

Yo le añadiría en B4XMainPage para copiar los archivos
He mirado en el zip y la carpeta contiene los archivos de Shared Files. ¿Qué haría esa línea que me indicas?


Para el clic de los label utilizo esto (que es bastante feo)
Parece que es buena solución, de hecho, Erel lo hace prácticamente igual en Pleroma.
Ya me funciona esa parte, gracias¡¡

Código de Erel:
#if B4J
Private Sub lblExit_MouseClicked (EventData As MouseEvent)
#else
Private Sub lblExit_Click
#end if
    imgAvatar_Click
End Sub

Utilizo soluciones multiplataforma para todo lo que puedo
Sí, por falta de costumbre, tuve que cambiar la declaración de los editText a B4XView.
No había caído en los BCToast, los meteré en mi código.

En cuanto a los dip, echaré un ojo a las dos soluciones que me decís.

Gracias¡¡
 

angel_

Well-Known Member
Licensed User
Longtime User
Gracias a los dos por los consejos:


He mirado en el zip y la carpeta contiene los archivos de Shared Files. ¿Qué haría esa línea que me indicas?
Copia los archivos compartidos a la carpeta Files de la plataforma que se esté ejecutando
 

josejad

Expert
Licensed User
Longtime User
Actualizado el primer post. He subido el proyecto de nuevo, funcionando en B4A y B4J. No lo he probado en B4i.

B4XProject.gif


saludos,
 

angel_

Well-Known Member
Licensed User
Longtime User
Para B4i he añadido la referencia relativa a las clases y las librerías, pero salen estos errores.

Captura_iOS.JPG



Librerias_iOS.JPG
 

Attachments

  • B4iProject.zip
    182.6 KB · Views: 338

josejad

Expert
Licensed User
Longtime User
Hey Angel:

Genial, gracias por probar.
Tienes que añadir la clase DBRequestManager y jRDC que están en la raíz del proyecto:
1612784713191.png



Es verdad que se me pasó poner la lista de librerías:
1612784724954.png
 

josejad

Expert
Licensed User
Longtime User
Sigues teniendo los errores entonces?
Main se comparte en B4i?

Según el tutorial de jRDC2, hay que añadir en Main los tipos DBResult y DBCommand (no sé dónde en B4i)
B4X:
Sub Process_Globals
    Type DBResult (Tag As Object, Columns As Map, Rows As List)
    Type DBCommand (Name As String, Parameters() As Object)
End Sub
 

angel_

Well-Known Member
Licensed User
Longtime User
No, el Main no se comparte, quizás sea mejor pasar los Type del Main a Process_Globals de un módulo estático. Hice los cambios ahora me salta el error en DBCommand (sigo investigando)

En B4i también da error (no existe GetKeyAt)
B4X:
mapData.Put(rs.Columns.GetKeyAt(i), record)
 

josejad

Expert
Licensed User
Longtime User
En B4i también da error (no existe GetKeyAt)
No sé si tendrá que ver, pero creo que has marcado la librería KVS que no es.
Ten en cuenta que Erel liberó no hace mucho KVS2 como librería interna en vez de como clase, y creo que no es compatible.

Si te fijas yo tengo marcada KeyValueStore2 (v2.21) y tú KeyValueStore (v2.30)
 

josejad

Expert
Licensed User
Longtime User
Echa un ojo también a este post en relación al error del cmd
 

angel_

Well-Known Member
Licensed User
Longtime User
Yo marcaría la nueva KeyValueStore para todas las plataformas, parece cambiando cmd por cmd1 funciona aunque aparecen otros errores, te informo si avanzo.
 

angel_

Well-Known Member
Licensed User
Longtime User
He cambiado cmd por cmd1 y la declaración de Parameters, busca #If B4A or B4J para ver los cambios a ver que te parecen ya que no puedo probar si funciona bien, no está totalmente probado.
 

Attachments

  • ProjectB4i.zip
    212.1 KB · Views: 303

josejad

Expert
Licensed User
Longtime User
Hola Ángel:

Ando liadillo estos días y no le he podido echar mucho tiempo a todo esto.

He probado tu ejemplo y no me aparecen datos, me aparece todo a Null.

Parece ser que el problema es que he usado el GetKeyAt, que es lo que te daba error a tí en B4i. Como lo has cambiado por Get, no funciona, en esta línea
B4X:
mapData.Put(rs.Columns.Get(i), record)

Indicaba Erel que no debe usarse GetKeyAt ya que no son multiplataforma

Deprecated methods - Map.GetKeyAt / GetValueAt - these methods were added before the For Each loop was available. They are not cross platform and are not the correct way to work with maps.

B4X:
'bad
For i = 0 To Map1.Size - 1
Dim key As String = Map1.GetKeyAt(i)
Dim value As String = Map1.GetValueAt(i)
Next

'good
For Each key As String In Map1.Keys
Dim value As String = Map1.Get(key)

Next

Tengo que ver cómo pasar los nombres de las columnas al mapa. Tengo reunión ahora, a ver si le echo un ojo luego, pero ahora no se me ocurre como meter el For Each dentro del otro bucle.

saludos,[/code]
 
Last edited:
Top