Ismael Marquez
Ismael Marquez

Reputation: 21

Java/Swing app Freezes randomly

I have a simple Swing button that refreshes a jtable, but after a random number of clicks the application freezes, sometimes indefinitely, sometimes it responds after a minute or so. I never did any thread especific method so I think maybe thats the issue but I dont know where to start or how to modify the methods if that is the cause of the freezes.

This is the code:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    recorrerLista();
}  


public EventList recorrerLista(){
    Persistir p = Persistir.getInstancia();
    Vector<Pedidos> lista2 = p.listarPedidos();
    Iterator it = lista2.iterator();
    if(!pedList.isEmpty()){
        pedList.clear();
    }
    while(it.hasNext()){
        Vector v = new Vector();
        v = (Vector) it.next();
        int index = (Integer)v.get(0);
        Pedidos ped = new Pedidos();
        ped = p.buscarPedidoPorId(index);
        pedList.add(ped);
    }
    return pedList;

}

Edit: I tried inserting the method of the persistence class (Persistir) inside a SwingWorker but now the UI don't show up.

Here is the code

public Vector listarPedidos() throws InterruptedException, ExecutionException{
SwingWorker listar = new SwingWorker<Vector, Vector>(){

    @Override
    protected Vector doInBackground() throws Exception {
        Vector<Articulos> lista = null;
  EntityManagerFactory emf = Persistence.createEntityManagerFactory("PedidosPU" );
  EntityManager em = emf.createEntityManager();
  em.getTransaction().begin();

  try {
    Query query = em.createNativeQuery("SELECT * FROM pedidosview WHERE ENTREGADO='P' ORDER BY fecha_pedido");

lista = (Vector) query.getResultList();
  } catch (Exception e) {
    System.out.println( e.getMessage() );
    em.getTransaction().rollback();
  } finally {
    em.close();
    emf.close();
  }
    return lista;
        }
  
 };
    return (Vector) listar.get();

}

Edit 2: I did what was suggested and i get a null pointer exception, here is my code:

public Vector listarPedidos(){
//Vector<Articulos> lista = null;
final EntityManagerFactory emf = Persistence.createEntityManagerFactory("PedidosPU" );
final EntityManager em = emf.createEntityManager();

final SwingWorker worker = new SwingWorker(){  
  private Vector lista;
  

  @Override
  protected Object doInBackground() throws Exception {
      em.getTransaction().begin();

    try {
      Query query = em.createNativeQuery("SELECT * FROM pedidosview WHERE ENTREGADO='P' ORDER BY fecha_pedido");

      lista = (Vector) query.getResultList();
    } catch (Exception e) {
      System.out.println( e.getMessage() );
      em.getTransaction().rollback();
    } finally {
      em.close();
      emf.close();
    }
      return lista;
    }


 };
   worker.execute();
   return lista;


}

Edit 3: I added this code to the ActionPerformed() of the button. But it seems to skip the code entirely

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    final Persistir p = Persistir.getInstancia();
    

    SwingWorker<Void, Pedidos> worker = new SwingWorker<Void, Pedidos>() {
        //private Vector lista2;
        @Override
        protected Void doInBackground() throws Exception {
            EntityManagerFactory emf = Persistir.createEntityManagerFactory("PedidosPU" );
            EntityManager em = emf.createEntityManager();

            String jqpl = "SELECT * FROM pedidosview WHERE ENTREGADO='P' ORDER BY fecha_pedido";
            //TypedQuery<Articulos> query = em.createQuery(jpql, Articulos.class);
            Query query = em.createNativeQuery("SELECT * FROM pedidosview WHERE ENTREGADO='P' ORDER BY fecha_pedido");
            //query.setParameter("param", "P");

            //lista = (Vector) query.getResultList();
            List<Pedidos> lista2 = query.getResultList();

            publish((Pedidos[])lista2.toArray());

            em.close();
            emf.close();
            return null;
        }

@Override
protected void process(List<Pedidos> chunks) {
    Iterator it = lista2.iterator();
            if(!pedList.isEmpty()){
            pedList.clear();
            }
            while(it.hasNext()){
            Vector v = new Vector();
            v = (Vector) it.next();
            int index = (Integer)v.get(0);
            Pedidos ped = new Pedidos();
            ped = p.buscarPedidoPorId(index);
            pedList.add(ped);
            }
}

@Override
protected void done() {
    jButton1.setEnabled(true);
}    
    };

worker.execute();
} 

Upvotes: 0

Views: 579

Answers (1)

dic19
dic19

Reputation: 17971

Your SwingWorker implementation is pretty much like if you don't have nothing at all, because at the end of listarPedidos() you call get() method:

public Vector listarPedidos() throws InterruptedException, ExecutionException {
    ...
    return (Vector) listar.get();
}

Thus causing the Event Dispatch Thread get blocked until doInBackground() is complete:

enter image description here

You should use publish() and process() instead. Since you use JPA, I'm assuming that you can manage to get an Entity called Articulos, so you could do something like this:

SwingWorker<Void, Articulos> worker = new SwingWorker<Void, Articulos>() {
    @Override
    protected Void doInBackground() throws Exception {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("PedidosPU" );
        EntityManager em = emf.createEntityManager();

        String jqpl = "SELECT a FROM Articulos a WHERE a.entregado = :param";
        TypedQuery<Articulos> query = em.createQuery(jpql, Articulos.class);
        query.setParameter("param", "P");

        List<Articulos> resultList = query.getResultList();

        publish((Articulos[])resultList.toArray());

        em.close();
        emf.close();
    }

    @Override
    protected void process(List<Articulos> chunks) {
        // add your items to the table model here
        // this code runs in the EDT
    }

    @Override
    protected void done() {
        refreshButton.setEnabled(true);
    }    
};

worker.execute();

Off-topic

Given the use of Vector classm I suspect your table model is DefaultTableModel (if this is not the case pelase disregard this off-topic comment), which is not the best ally to work with complex model classes.

If this is the case (and given the fact you seem to speak Spanish), please see this post (in Spanish) (or in English, courtesy of google translate) about creating a reusable table model using domain classes. If you don't speak Spanish, you still could look at the GenericDomainTableModel class code posted at the end of this entry (or in English) because, well, it's pretty self-explanatory.

Upvotes: 6

Related Questions