Native JavaScript functions within Vaadin

I’ve been developing an Application since 2015 March (moreover). From the beginning, what I wanted was using Hibernate and a DAO pattern for Data Access (I’m using PostgreSql database). This would be the architecture (don’t laugh at me, I drawed using paint :p):

Everything has been working, somehow, correctly. Now, we need to introduce Google Charts to our application. Google charts. To use common and plain javascript code, my solution has been creating a Custom Component with a Label, containing HTML code (div). Then executing a javascript function, which loads a google chart and renders it in the div. So, I developed a Restful WS to interact with the database. The architecture is what follows:
However, I’m facing some problems.

  • When I execute the methods of the WS, the results are always identical (you’ll know afterwards why I say identical).
  • When the page is loaded (the View), the results returned by the WS aren’t correct. This is a DAO method to fetch some values:
    public HashMap<LocalDate, Integer> getCantidadDeRutasPorPlanes(LocalDate pInicio, LocalDate pFin){

        System.out.println("getCantidadDeRutasPorPlanes() entre " 
        + DateTimeFormatters.JavaDateTimeFormatter.formatDate(pInicio)
        + " y "
        + DateTimeFormatters.JavaDateTimeFormatter.formatDate(pFin));

        HashMap<LocalDate, Integer> ret = new HashMap<LocalDate, Integer>();
        
        for(LocalDate aux = pInicio; 
                aux.isBefore(pFin) || aux.isEqual(pFin); 
                aux = aux.plusDays(1)){
            Integer value = getCantidadDeRutasPorPlan(aux);
            ret.put(aux, value);
        }
        
        return ret;
        
    }

    private Integer getCantidadDeRutasPorPlan(LocalDate pFecha) {

        try{

            Query q = session
                    .createQuery("select size(p.lasRutas) from Plan p where day(p.laFecha)=:dia and month(p.laFecha)=:mes and year(p.laFecha)=:anyo");
            q.setInteger("dia", pFecha.getDayOfMonth());
            q.setInteger("mes", pFecha.getMonthValue());
            q.setInteger("anyo", pFecha.getYear());
    
            Integer cantidad = 0;
    
            List lista = q.list();
            if(lista != null){
                
                if(!lista.isEmpty()){
                    for (Object obj : lista) {
                        if(obj != null){
                            Integer cant = (Integer) obj;
                            cantidad += cant;
                        }
                    }
                }
                
            }
            
            System.out.println("getCantidadDeRutasPorPlan(): " + cantidad);
            return cantidad;

        }catch(HibernateException e){
            logger.error("Error HibernateException en getCantidadDeRutasPorPlan(): " + e.getMessage());
            System.err.println("Error HibernateException en getCantidadDeRutasPorPlan(): " + e.getMessage());
            e.printStackTrace();
            return -1;
        }
        
    }

As you can see, when an exception is caught the returned value is -1. So, when loading the page and drawing charts, several exceptions happen and pseudo-random data is loaded. E.g: 0,0,-1,-1,-1,0,0,-1,0,-1…

However, when calling manually (with SOAP UI) the WS method which executes the same DB method, the results are correct, e.g. 0,0,0,2,0,0,1,0,0,…

With regard to the web service i guess there is no problem. So, there are two possible reasons why this doesn’t work correctly:

  1. I’m using a trick to make google charts work on Vaadin. Perhaps I should integrate it with server-client side methodology of Vaadin as said
    here
    . I know JavaScript is executed on the client side. Vaadin, on the other hand, is server side. The
    Web Service
    is executed on the server,
    using the same dao
    .
  2. Otherwise, as you can see in bold, the problem may be the following: vaadin application and the web service both share the same DAO class. I didn’t want to introduce code (at least the relevant code) regarding the DAO, but now I consider helpful so that anybody can comment out her/his impression.
  • PtDao is the DAO class itself and follows
    Singleton
    pattern, where all the stuff related to Hibernate, HQL and session is located.
  • PtService is an interface. It contains every method of PtDao which is wanted to be usable.
  • PtDaoService implements PtService and it contains the instance of PtDao as attribute. So, in every method (which is named equally as in PtDao) it’s called dao.theMethod(params);

Let’s see in action:
PtDao

public class PtDao {

    /*
     * Atributos
     */
    private Logger logger = LoggerFactory.getLogger(PtDao.class);

    private ConfiguracionNueva config;
    
    private static PtDao myPtDao = null;
    
    private Configuration cfg;
    private SessionFactory factory;
    private Transaction tx;
    private static Session session;
    private static ServiceRegistry serviceRegistry;

    // Flota is a singleton which contains cars and drivers (two lists)
    private Flota flota = Flota.getInstance();

    /*
     * Métodos
     */
    private PtDao() {

        try {

            config = new ConfiguracionNueva();
            config.leerConfiguracion();
            
            //cfg = new Configuration().configure("hibernate.cfg.xml"); // configures settings from hibernate.cfg.xml

            cfg = new Configuration();
            
            //cfg.configure();
            cfg.setProperty("hibernate.hbm2ddl.auto", "update");
            cfg.setProperty("hibernate.transaction.auto_close_session", "false");
            cfg.setProperty("hibernate.connection.autocommit", "false");

            // Configuración PostgreSQL
            cfg.setProperty("hibernate.connection.driver_class", "org.postgresql.Driver");
            cfg.setProperty("hibernate.connection.url", "jdbc:postgresql://" 
                    + config.getIP_POSTGRESQL() + ":"
                    + config.getPORT_POSTGRESQL() + "/"
                    + config.getDATABASE_POSTGRESQL());

            cfg.setProperty("hibernate.connection.username", config.getUSERNAME_POSTGRESQL());
            cfg.setProperty("hibernate.connection.password", config.getPASSWORD_POSTGRESQL());
            
            cfg.setProperty("dialect", "org.hibernate.dialect.PostgreSQLDialect");
            
            // C3p0 connection pool
            cfg.setProperty("connection.provider_class", "org.hibernate.connection.C3P0ConnectionProvider");
            cfg.setProperty("c3p0.min_size", "3");
            cfg.setProperty("c3p0.max_size", "10");
            cfg.setProperty("c3p0.timeout", "1000");
            cfg.setProperty("c3p0.idle_test_period", "2000");
            cfg.setProperty("c3p0.preferredTestQuery", "select 1;");
            cfg.setProperty("hibernate.connection.release_mode", "after_transaction");
            
            cfg.setProperty("hibernate.show_sql", "false");
            cfg.setProperty("hibernate.format_sql", "true");
            cfg.setProperty("hibernate.generate_statistics", "true");
        
            // Meter clases y ficheros HBM
            cfg.addResource("com/ingartek/cavwebapp/model/LatLng.hbm.xml");
            // more hibernate mappings

            StandardServiceRegistryBuilder serviceRegistryBuilder = new StandardServiceRegistryBuilder();

            // If you miss the below line then it will complain about a missing
            // dialect setting
            serviceRegistryBuilder.applySettings(cfg.getProperties());

            serviceRegistry = serviceRegistryBuilder.build();
            factory = cfg.buildSessionFactory(serviceRegistry);
            this.openSession();
            
        } catch (ConfigurationException e) {
            System.err.println("Error ConfigurationException en PtDao(): " + e.getMessage() + ". Causa: " + e.getCause());
            logger.error("Error ConfigurationException en PtDao(): " + e.getMessage() + ". Causa: " + e.getCause());
            e.printStackTrace();
        } catch (HibernateException e) {
            System.err.println("Error HibernateException en PtDao(): " + e.getMessage() + ". Causa: " + e.getCause());
            logger.error("Error HibernateException en PtDao(): " + e.getMessage() + ". Causa: " + e.getCause());
            e.printStackTrace();
        }

    }

    private void openSession() throws HibernateException {
        session = factory.openSession();
    }

    private void closeSession() {
        session.close();
    }

    private void beginTransaction() {
        this.tx = null;
        this.tx = session.beginTransaction();
    }

    private void commitTransaction() throws HibernateException {
        this.tx.commit();
    }

    private void rollbackTransaction() throws HibernateException {
        if (this.tx != null)
            this.tx.rollback();
    }

    public static PtDao getPtDao() {
        if (myPtDao == null) {
            myPtDao = new PtDao();
        }
        return myPtDao;
    }

    // Login: simple login
    public Administrador loginAdministrador(String pUsername, String pPassword)
            throws IncorrectPasswordOrUserNotFoundException {

        System.out.println("Intentando identificar a " + pUsername);

        Query q = session
                .createQuery("from Administrador as ad where ad.user=:username and ad.pass=:password");
        q.setString("username", pUsername);
        q.setString("password", pPassword);

        @SuppressWarnings("unchecked")
        Iterator<List<Administrador>> it = q.list().iterator();

        if (!it.hasNext()) {
            throw new IncorrectPasswordOrUserNotFoundException(pUsername);
        } else {
            Administrador admin = (Administrador) it.next();
            return admin;
        }

    }
    
    ...
    
    // Simple write method
    public Vehiculo anadirVehiculo(String pMatricula, String pNombre,
            Integer pAsientos) throws ExisteVehiculoException {
        System.out.println("Creando nuevo vehículo");

        if (!isMatriculaUsada(pMatricula)) {

            Vehiculo unVehiculo = new Vehiculo(pMatricula, pNombre, pAsientos);

            if (!flota.existeVehiculo(unVehiculo)) {
                flota.anadirVehiculo(unVehiculo);
            }

            try {
                beginTransaction();
                session.save(unVehiculo);
                commitTransaction();
                return unVehiculo;
            } catch (HibernateException e) {
                System.err
                        .println("Error HibernateException en anadirVehiculo(): "
                                + e.getMessage() + ". Causa: " + e.getCause());
                e.printStackTrace();
                return null;
            }

        } else {
            rollbackTransaction();
            throw new ExisteVehiculoException();
        }

    }

    ...
    
    // One of the methods to draw Google Charts
    public HashMap<LocalDate, Integer> getCantidadDeRutasPorPlanes(LocalDate pInicio, LocalDate pFin){

        System.out.println("getCantidadDeRutasPorPlanes() entre " 
        + DateTimeFormatters.JavaDateTimeFormatter.formatDate(pInicio)
        + " y "
        + DateTimeFormatters.JavaDateTimeFormatter.formatDate(pFin));

        HashMap<LocalDate, Integer> ret = new HashMap<LocalDate, Integer>();
        
        for(LocalDate aux = pInicio; 
                aux.isBefore(pFin) || aux.isEqual(pFin); 
                aux = aux.plusDays(1)){
            Integer value = getCantidadDeRutasPorPlan(aux);
            ret.put(aux, value);
        }
        
        return ret;
        
    }

    private Integer getCantidadDeRutasPorPlan(LocalDate pFecha) {

        try{

            Query q = session
                    .createQuery("select size(p.lasRutas) from Plan p where day(p.laFecha)=:dia and month(p.laFecha)=:mes and year(p.laFecha)=:anyo");
            q.setInteger("dia", pFecha.getDayOfMonth());
            q.setInteger("mes", pFecha.getMonthValue());
            q.setInteger("anyo", pFecha.getYear());
    
            Integer cantidad = 0;
    
            List lista = q.list();
            if(lista != null){
                
                if(!lista.isEmpty()){
                    for (Object obj : lista) {
                        if(obj != null){
                            Integer cant = (Integer) obj;
                            cantidad += cant;
                        }
                    }
                }
                
            }
            
            System.out.println("getCantidadDeRutasPorPlan(): " + cantidad);
            return cantidad;

        }catch(HibernateException e){
            logger.error("Error HibernateException en getCantidadDeRutasPorPlan(): " + e.getMessage());
            System.err.println("Error HibernateException en getCantidadDeRutasPorPlan(): " + e.getMessage());
            e.printStackTrace();
            return -1;
        }
        
    }
    

PtService

public interface PtService {

    public Administrador loginAdministrador(String pUsername, String pPassword) throws IncorrectPasswordOrUserNotFoundException;
    public Vehiculo anadirVehiculo(String pMatricula, String pNombre, Integer pAsientos) throws ExisteVehiculoException;
    public HashMap<LocalDate, Integer> getCantidadDeRutasPorPlanes(LocalDate pInicio, LocalDate pFin);
    
}

PtDaoService

[code]
public class PtDaoService implements PtService {

/*
 * Atributos
 */
private PtDao dao;

/*
 * Métodos
 */
public PtDaoService(){
    this.dao = PtDao.getPtDao();
}

@Override
public Administrador loginAdministrador(String pUsername, String pPassword)
        throws IncorrectPasswordOrUserNotFoundException {
    return dao.loginAdministrador(pUsername, pPassword);
}

@Override
public Vehiculo anadirVehiculo(String pMatricula, String pNombre,
        Integer pAsientos) throws ExisteVehiculoException{
    return dao.anadirVehiculo(pMatricula, pNombre, pAsientos);
}

@Override
public HashMap<LocalDate, Integer> getCantidadDeRutasPorPlanes(LocalDate pInicio, LocalDate pFin) {
    return dao.getCantidadDeRutasPorPlanes(pInicio, pFin);
}

}
[/code]Do you see any trouble in here?

What do you think of my approach?

Thanks in advance…

Should I integrate my JS component using this
guide
?