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

Ayuda en aplicación de escritorio.

Hola a todos,
Estoy desarrollando una aplicacion que en principio crei pequeña y se ha ido creciendo cada vez más. Al punto que siento que se me sale de las manos.

Uno de mis principales problemas es que la aplicacion es de escritorio y no se si hay forma de optimizar la conexión a la base de datos, en mi caso mysql, debido a que constantemente unos equipos me envian informacion a la base de datos y por esta razón debo estar leyendo constantemente desde el aplicativo la información. Esto se hace exactamente cada 6 segundos, pero para filtrar todos los eventos que se envian a la base de datos uso procedimeitnos almacenados que tardan hasta 28 segundos en enviar los resultados. De momento eso es lo que me tiene mas preocupado. El servidor de base de datos es un mysql 5 y esta montado sobre un servidor Centos, la conexion a la base de datos la hago de la sgte forma.

public static Connection getConnectionDB() {

                if (conn == null)
                        conectar();

                try {
                        if (conn != null)
                                if (conn.isClosed()) {
                                        conn = null;
                                        System.out.println("no connected");
                                }

                } catch (SQLException e) {
                        System.out.println("isClosed");
                }

                return conn;
        }

        public static Connection conectar() {
                try {
                        Class.forName(driver);
                } catch (ClassNotFoundException e) {
                        System.out.println("Driver");
                }

                try {
                        conn = DriverManager.getConnection(url + db, user, pass);
                } catch (SQLException e) {
                        conn = null;
                        JOptionPane.showMessageDialog(null, "No se puede establecer conexión con el servidor");
                        System.gc();
                }

                return conn;

        }

        public boolean close() {
                try {
                        conn.close();
                        conn = null;
                        return true;
                } catch (SQLException e) {
                        e.printStackTrace();
                        return false;
                }
        }

De Antemano muchas gracias por lo que me puedan aportar.

Opciones de visualización de comentarios

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

Pools

De entrada te recomiendo que uses un pool de conexiones a base de datos, para que no establezcas una conexión cada 6 segundos, sino que se reutilizan las que ya tengas establecidas (y siendo aplicación de escritorio no creo que uses más de 2 o 3).

En vez de manejar una Connection directamente, vas a tener un DataSource al cual le pides conexiones donde sea que las necesites, las usas y las cierras (cuando las cierras, realmente lo que sucede es que se devuelven al pool, pero se quedan abiertas, listas para usarse nuevamente).

Supongo que usas un java.util.Timer o (preferentemente) un java.util.concurrent.ScheduledExecutor para calendarizar la tarea que dices que se tiene que hacer cada 6 segundos. Si es exactamente cada 6 segundos pero el server está ocupado porque realmente se tarda 28 segundos en realizarla, pues de entrada creo que convendría cambiar el tiempo, subirlo un poco. Pero en caso que se pueda optimizar algo en el server, creo que lo conveniente es que el Runnable (o TimerTask) que corre la tarea, tenga alguna bandera para saber que se está realizando y que no se debe realizar nuevamente hasta que termine; de esa manera aunque se active la tarea cada 6 segundos, si todavía no termina de la ejecución anterior, no se realiza nuevamente; cuando la ejecución actual termine, resetea la bandera y en la siguiente activación de la tarea ya se realizará nuevamente.

Gracias por responder, la

Gracias por responder, la verdad tenia un error de concepto, yo pensaba que los pool de conexiones eran exclusivos para aplicaciones Web creyendo que era necesario el uso de un servidor de aplicacion como JBoss. En cuanto a la tarea programa, si estoy usando un java.util.Timer para la realización de la tarea, supongo que la otra clase que me mencionas es mucho mejor me encargare de estudiarla. Ya estoy leyendo c3p0 para implementar el pool, gracias y estare comentando como me fue.
Por otro lado tengo una duda acerca de java.util.Properties, estos archivos solo se pueden leer al momento de ejecutar la aplicacion?, lo que pasa es que mi aplicación tengo un servidor que se encarga de recibir conexiones por socket y generalmente es propenso a que se pierda la conexión con los dispositivos, lo que genera la muerte del hilo. Mi duda es si puedo usar el properties para almacenar algunos valores cada vez que se conecta un dispositivo con eso puedo usar algunos datos que me envio el dispositivo antes de perder la conexion, como una especie de variables de sesion. Gracias por todo.

Imagen de ezamudio

técnicamente...

No hay razón para que no puedas guardar datos en el servidor en un archivo .properties pero pues no es lo más recomendable... cómo los vas a identificar? Tienes que usar el identificador del cliente, por lo que sólo puedes guardarlos cuando el cliente ya está identificado. Y qué pasa si ya existe un archivo con eso? cuál es la finalidad de guardarlo? seguramente lo quieres para cargar de nuevo esos datos en la siguiente conexión?

mmmm sip

Lo que pasa es que los dispositivos se encargan de enviarme eventos- uno a la vez - y muchas veces un evento es el inicio de un reporte y luego llega un evento donde se finaliza el reporte. El problema es que si la conexión se pierde y pasa muy seguido porque son dispositivos que usan 3gsm. Si pasa esto, los datos que llevaba en el hilo se pierden y en caso que llegue un evento que finaliza un reporte los datos que tenia guardados del evento anterior se me han perdido. Busco solución a ese problema con lo del properties. Los dispositivos se identifican cada vez que envían un evento ya que este tiene asociado el identificador de cada dispositivo.

Imagen de ezamudio

Entonces puedes usar el

Entonces puedes usar el identificador del dispositivo como el nombre del archivo .properties y así los identificas; en el evento de generar el reporte creas o sobreescribes el properties y en el evento de finalizar reporte lo borras. Eso también lo podrías hacer marcando un status en el registro del dispositivo en la base de datos, teniendo una tabla con los datos que necesitas guardar y manejas un registro por cada dispositivo.

Si manejas los .properties asegúrate de que los guardas en un directorio que no sea el temporal o que no esté muy a la vista para que no llegue algún usuario ajeno a tu aplicación en el servidor y diga "qué es esto? bah, no parece que sirvan, los voy a borrar".

Gracias

Gracias por la ayuda, de momento ya estoy implementando el pool y hasta el momento todo va bien. Luego me encargare del properties o si considero mejor, el registro en la base de datos, teniendo en cuenta tus observaciones. Tu ayuda me hizo dar buenos avances, muy agradecido. Saludos

Problemas Pool

Hola, implementando el pool de conexiones me esta saliendo lo siguiente después que la aplicacion a realizado unas consultas y continua con otras. java.sql.SQLException: You can't operate on a closed Statement!!! .

Estoy realizando la implementacion de la siguiente forma:

En mi fachada tengo:

private ControlVehiculosRuta controlVehiculosRuta;
        private Connection conn = null;
        private ConnectionDS connectionDS;

        public VehiculoRutaFacade() {
                controlVehiculosRuta = new ControlVehiculosRuta();
                connectionDS = new ConnectionDS();
        }

        public ArrayList<VehiculoDTO> getVehiculosRuta(int idRuta) {
                conn = connectionDS.getConnection();

                if (conn != null) {
                        ArrayList<VehiculoDTO> vehiculos = controlVehiculosRuta.getVehiculosRuta(conn, idRuta);
                        try {
                                if(conn != null)conn.close();
                        } catch (SQLException e) {
                                e.printStackTrace();
                        }
                        conn = null;
                        return vehiculos;
                }

                return null;
        }

El pool:

public ConnectioPool() throws PropertyVetoException{
               
                ds = new ComboPooledDataSource();
                ds.setDriverClass( "com.mysql.jdbc.Driver" ); //loads the jdbc driver            
                ds.setJdbcUrl( "" );
                ds.setUser("");                                  
                ds.setPassword("");                                  
                       
                // the settings below are optional -- c3p0 can work with defaults
                ds.setMinPoolSize(5);                                    
                ds.setAcquireIncrement(5);
                ds.setMaxPoolSize(20);         
        }
       
        public static DataSource getDataSource(){
                return ds;
        }

Y en el genericDAO:

public List<VO> callStorageQuery(String procedure) throws SQLException {

                StringBuffer sql = new StringBuffer("{Call " + procedure + "()}");

                CallableStatement cs = connection.prepareCall(sql.toString());

                ResultSet rs = cs.executeQuery();

                List<VO> list = new ArrayList<VO>();

                while (rs.next()) {
                        list.add(creator.create(rs));
                }
                attemptClose(rs);
                attemptClose(cs);

                return list;
        }

Gracias

Imagen de ezamudio

manejo de conexiones

Al usar un pool, debes cambiar la manera en que usas las conexiones. No debes retener conexiones en ningún componente tuyo; es mejor que retengas referencia al DataSource y cuando necesites conexiones usas una. En este metodo, el método callStorageQuery parece que usa una conexión ya abierta previamente; eso está mal. Debe crear una conexión dentro del método, usarla y al final cerrarla (pon todo dentro de un try-finally para que SIEMPRE le hagas close() a la conexión y se devuelva al Pool):

public void metodo() throws SQLException {
  Connection conn = dataSource.getConnection();
  try {
    //haces tus cosas con la conexion
  } finally {
    conn.close();
  }
}

Solucionado Manejo de conexiones

Efectivamente estaba iniciando la conexión en mi fachada y luego la pasaba por capas hasta llegar a los DAOs. Gracias ezamudio por compartir tu experiencia y ayudarme a mejorar mi conocimiento.

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