I was trying to simplify the following lines with java 8

this.audiencias = new ArrayList<>();
        for(Audiencia audiencia: carpeta.getAudiencias()){
            this.audiencias.add(new AudienciaDTO(audiencia));
        }

to this

this.audiencias = carpeta.getAudiencias.stream().map(AudienciaDTO::new).collect(Collectors.toList());

although it seems correct, and no error was thrown, it was returning an empty list.

As it happens, the list type is important. The attribute this.audiencias is of type Collection and carpeta.getAudiencias returns the same type, but the method stream() apparently only works with List types.

If I change the code to

List<Audiencia> asList = new ArrayList(carpeta.getAudiencias());
        this.audiencias = asList.stream().map(AudienciaDTO::new).collect(Collectors.toList());

it works as expected, but it is cumbersome the need to convert the Collection to a List type first.

for a one liner it would be

this.audiencias = new ArrayList<>(carpeta.getAudiencias()).stream().map(AudienciaDTO::new).collect(Collectors.toList());

fuentes:
http://tutorials.jenkov.com/java-collections/streams.html
https://docs.oracle.com/javase/tutorial/collections/interfaces/index.html

Anuncios

I’ve installed netbeans on Ubuntu 16.04 from the official repositories.

sudo apt-get install netbeans

It opened correctly but I noticed it didn’t have all the plugins I required. First, i tried to install them from “Help | About | Plugins”. It complained about not having permission to extract/install the plugin. So, I closed netbeans and started it with root user, then it finished adding the plugins but when I tried to start it again with my regular user it wouldn’t boot.

I decided to remove netbeans repositorie’s version and instead download and install manually.

sudo apt-get purge netbeans

I’ve downloaded and extracted the OS independent full version of netbeans on my home directory ‘~/Apps/netbeans/8.1’ but when I tried to start it from the terminal nothing happened.

As it happens, the problem was that when I started netbeans as root it changed ownership of some files on two folders: ~/.netbeans and ~/.cache/netbeans

The solution is to delete those folders (those will be recreated when starting netbeans) and start netbeans again as a regular user.

sudo rm -rf ~/.netbeans ~/.cache/netbeans

Sources:
https://bbs.archlinux.org/viewtopic.php?id=164323
http://wiki.netbeans.org/FaqLogMessagesFile

Aunque ya no es necesario utilizar un servidor de aplicaciones como glassfish en nuestras aplicaciones, áun tenemos algunas que se ejecutan en uno.

Ahora me tocó instalar un servidor de aplicaciones desde cero. Entonces lo primero que hice fue instalar Ubuntu Server.
Una vez instalado, descargué Glassfish (Web Profile) con el comando:

wget http://download.java.net/glassfish/4.1/release/glassfish-4.1-web.zip -O ~/glassfish-4.1-web.zip

Para descomprimir el archivo, necesitamos primero instalar la herramienta unzip mediante el comando:

sudo apt-get install unzip

Para ejecutar el servidor vamos a necesitar, también, instalar java

sudo apt-get install openjdk-7-jdk

una vez instalados, hay que extraer los archivos de glassfish en alguna carpeta (yo elegí /opt)

cd /opt/
unzip ~/glassfish-4.1-web.zip

vamos a cambiar el propietario y el grupo de la carpeta por el nuestro

sudo chown usuario:grupo -R /opt/glassfish4

vamos a agregar temporalmente la carpeta de glassfish a nuestro PATH (también puedes hacerlo permanente) con el siguiente comando

export PATH=/opt/glassfish4/bin:$PATH

y vamos a iniciar el servidor de la siguiente manera

asadmin start-domain

si todo va bien, veremos el mensaje

Successfully started the domain : domain1
domain  Location: /opt/glassfish4/glassfish/domains/domain1
Log File: /opt/glassfish4/glassfish/domains/domain1/logs/server.log
Admin Port: 4848
Command start-domain executed successfully.

Ahora hay que abrir en un navegador la ip del servidor en el puerto 4848. Dado que Ubuntu Server no tiene instalado por defecto una interfaz gráfica, tenemos que hacerlo desde otra computadora.
Por default Ubuntu server bloquea todos los puertos. Entonces tenemos que abrir el puerto 4848 para poder acceder a la consola de glassfish.

sudo ufw enable
sudo ufw allow 4848

Nota: Si tenías instalado el servidor ssh tienes que abrir nuevamente el puerto mediante el comando sudo ufw allow 22. Si no, puedes instalarlo con el comando

sudo apt-get install openssh-server

Al ingresar a la url, por ejemplo http://glassfish-server:4848 o http://192.168.0.15:4848

nos va a mostrar un error que dice que debemos activar la administración segura para poder acceder a la consola de forma remota

Configuration Error
Secure Admin must be enabled to access the DAS remotely.

para activar esto debemos primero asignar una contraseña para el usuario admin

asadmin change-admin-password
asadmin restart-domain

y luego ejecutar

asadmin enable-secure-admin
asadmin restart-domain

Si sólo ejecutas el comando enable-secure-admin te mostrará el siguiente error

remote failure: At least one admin user has an empty password, which secure admin does not permit. Use the change-admin-password command or the admin console to create non-empty passwords for admin accounts.
Command enable-secure-admin failed.

Listo, ya podemos entrar a la consola y, por ejemplo, hacer el deploy de nuestra aplicación.

Fuentes:
https://glassfish.java.net/documentation.html
https://charleech.wordpress.com/2012/03/23/glassfish-version-3-1-2-secure-admin-must-be-enabled-to-access-the-das-remotely/
https://help.ubuntu.com/community/EnvironmentVariables

La validación de los datos de entrada es indispensable en cualquier aplicación. En las aplicaciones web tenemos que validar del lado del servidor y, es recomendable, validar del lado del cliente.

A continuación veremos como podemos validar del lado del cliente los campos de fecha de un formulario en SmartGWT.

En nuestro caso, tenemos un formulario sencillo donde se capturan dos fechas. Dado que estas fechas nos representan un rango, la fecha de fin siempre debe ser posterior a la fecha de inicio. En este caso se debe validar cuando cambie cualquiera de los dos campos. En SmartGWT lo podríamos realizar de la siguiente manera:

DynamicForm frmAudiencia = new DynamicForm();
DateTimeItem itmInicio = new DateTimeItem("inicio", "Inicio");
itmInicio.setType("datetime");
itmInicio.setShowPickerTimeItem(true);
itmInicio.setValidateOnChange(true);
DateTimeItem itmFin = new DateTimeItem("fin", "Fin");
itmFin.setType("datetime");
itmFin.setShowPickerTimeItem(true);
itmFin.setValidators(new CustomValidator() {
    {
        setDependentFields(new String[]{"inicio"});
    }
    @Override
    protected boolean condition(Object value) {
        return getRecord().getAttributeAsDate("inicio").before((Date) value);
    }
});
itmFin.setValidateOnChange(true);
frmAudiencia.setItems(itmNuc, itmTipoAudiencia, itmInicio, itmFin, itmJuez, itmSala);

De esta forma, cuando se modifique cualquiera de las dos fechas, se ejecuta el proceso de validación.

Fuentes:
http://smartclientexperience.wordpress.com/2011/10/19/introduction-to-smartclient-8-1smartgwt-2-5-validation-part-3/
http://www.smartclient.com/smartgwt/javadoc/com/smartgwt/client/widgets/form/validator/CustomValidator.html

Java – Maven o Gradle

noviembre 4, 2014

Maven

Maven es una herramienta de software para la gestión y construcción de proyectos Java –Wikipedia

Gradle

Gradle es una herramienta de automatización de proyecto que se basa en los conceptos de Apache Ant y Maven e introduce un lenguaje específico de dominio (DSL) basado en Groovy en lugar de la forma más tradicional de declarar la configuración del proyecto con XML.
Gradle fue diseñado para una solución multi-proyecto que puede llegar a ser bastante grande, y es compatible con compilaciones incrementales que determina inteligentemente qué partes del árbol de construcción han sido actualizadas, por lo que ninguna tarea dependendiente va a ser re-ejecutada. –Wikipedia

Hasta ahora había utilizado Maven como herramienta de gestión de proyectos, pero la siguiente afirmación me ha hecho pensar en utilizar Gradle para los nuevos proyectos

Google adopted Gradle as the default build tool for the Android OS –technologyconversations.com

Fuentes:
http://technologyconversations.com/2014/06/18/build-tools/

La mayoría de aplicaciones requieren acceso a una base de datos. En java existe JDBC que nos permite realizar esta tarea.
En una aplicación distribuida y escalable nos vemos en la necesidad de utilizar un pool de conexiones para no causar un problema de rendimiento. Por ejemplo, he creado servicios web (REST) que deseo sean consumidos desde dispositivos móviles, para ello necesito que los servicios sean escalables.

Ya que utilicé Spring Roo para crear la plantilla inicial del proyecto, este me agregó la siguiente configuración inicial.

applicationContext.xml

...
    <bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
        <property name="driverClassName" value="${database.driverClassName}"/>
        <property name="url" value="${database.url}"/>
        <!--<property name="username" value="${database.username}"/>-->
        <!--<property name="password" value="${database.password}"/>-->
        <property name="testOnBorrow" value="true"/>
        <property name="testOnReturn" value="true"/>
        <property name="testWhileIdle" value="true"/>
        <property name="timeBetweenEvictionRunsMillis" value="1800000"/>
        <property name="numTestsPerEvictionRun" value="3"/>
        <property name="minEvictableIdleTimeMillis" value="1800000"/>
        <property name="validationQuery" value="SELECT 1 FROM DUAL"/>
    </bean>
...

como podemos ver, esta configuración crea un DataSource de tipo org.apache.commons.dbcp.BasicDataSource. Este tipo de DataSource crea un pool de conexiones automáticamente. Genial!

Ahora, ¿cómo lo utilizamos en nuestras clases para poder ejecutar una consulta SQL?

Podríamos utilizarlo de la forma tradicional con JDBC

...
    @Autowired
    public DistritosServiceImpl(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public List<Distrito> getDistritos() {
        List<Distrito> distritos = new ArrayList<Distrito>();
        String sql = 
                "select id, nombre " +
                        "from distritos";
        Connection con = null;
        try{
            con = this.dataSource.getConnection();
            PreparedStatement stmt = con.prepareStatement(sql);
            ResultSet rs = stmt.executeQuery();
            while(rs.next()){
                distritos.add(new Distrito(rs.getInt("id"), rs.getString("nombre")));
            }
        }catch (Exception e){
            e.printStackTrace();
            if(con != null){
                try {
                    con.close();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return distritos;
    }
...

pero existe una mejor manera, utilizando JdbcTemplate

...
    @Autowired
    public DistritosServiceImpl(DataSource dataSource) {
        this.dataSource = dataSource;
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Override
    public List<Distrito> getDistritos() {
        String sql =
                "select id, nombre " +
                        "from distritos";
        return jdbcTemplate.query(sql, new RowMapper<Distrito>() {
            @Override
            public Distrito mapRow(ResultSet rs, int i) throws SQLException {
                return new Distrito(rs.getInt("id"), rs.getString("nombre"));
            }
        });
    }
...

Fuentes:

I have a Java application configured with Maven. I have all my model and web services in this application (backend). In a Java app normally you would have your web client code in src/main/webapp (frontend). I scaffold-ed the client application with yeoman, so it uses grunt to build and bower to manage dependencies. Great! well, not so much, it runs perfectly in my local environment (I can run bower install, then grunt build and it would generate a “dist” folder with all my sources compiled and minified) but it doesn’t work on heroku’s platform.

The problem is heroku detects my app only as Java application so it doesn’t run bower install nor grunt build.

I tried to use heroku-buildpack-multi with some issues, I even created my own patched version that allows to specify a base path for each buildpack. With that I can push to heroku and it runs mvn package and then npm install for the node buildpack. I’ve added a postinstall script to run both bower install and grunt build, which in turn you need to add as dependencies in your package.json.

{
  "name": "webapp",
  "version": "0.0.0",
  "dependencies": {
    "grunt": "^0.4.1",
    "grunt-cli": "~0.1.13",
    "bower": "~1.3.9",
    "grunt-autoprefixer": "^0.7.3",
    "grunt-concurrent": "^0.5.0",
    "grunt-contrib-clean": "^0.5.0",
    "grunt-contrib-compass": "^0.7.2",
    "grunt-contrib-concat": "^0.4.0",
    "grunt-contrib-connect": "^0.7.1",
    "grunt-contrib-copy": "^0.5.0",
    "grunt-contrib-cssmin": "^0.9.0",
    "grunt-contrib-htmlmin": "^0.3.0",
    "grunt-contrib-imagemin": "^0.7.0",
    "grunt-contrib-jshint": "^0.10.0",
    "grunt-contrib-uglify": "^0.4.0",
    "grunt-contrib-watch": "^0.6.1",
    "grunt-filerev": "^0.2.1",
    "grunt-google-cdn": "^0.4.0",
    "grunt-karma": "^0.8.3",
    "grunt-newer": "^0.7.0",
    "grunt-ngmin": "^0.0.3",
    "grunt-svgmin": "^0.4.0",
    "grunt-usemin": "^2.1.1",
    "grunt-wiredep": "^1.7.0",
    "jshint-stylish": "^0.2.0",
    "karma": "^0.12.17",
    "karma-jasmine": "^0.1.5",
    "karma-phantomjs-launcher": "^0.1.4",
    "load-grunt-tasks": "^0.4.0",
    "time-grunt": "^0.3.1"
  },
  "engines": {
    "node": "&gt;=0.10.0"
  },
  "scripts": {
    "test": "grunt test",
    "postinstall": "./node_modules/bower/bin/bower install &amp;&amp; ./node_modules/grunt-cli/bin/grunt build"
  }
}

It effectively run bower install and then grunt build, but it failed because my scaffold-ed client uses compass which in turn requires ruby, arrrgh! This is where I stopped looking into this path, I’ve decided to build on my local computer and include the “dist” folder on source control (against all my principles), as suggested by various websites, for now.

Sources:
https://github.com/ddollar/heroku-buildpack-multi
https://discussion.heroku.com/t/grunt-task-after-deployment/253