jhipster – configure elasticsearch analyzer for a field

jhipster-elastic

We have an Entity with an Enum field. This enum field gets saved in the database as string.

enum

public enum TipoContrato {
    ADJUDICACION_DIRECTA,  INVITACION_RESTRINGIDA,  LICITACION_PUBLICA
}

entity

@Entity
@Table(name = "contrato")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Document(indexName = "contrato")
public class Contrato implements Serializable {

    ...

    @Enumerated(EnumType.STRING)
    @Column(name = "tipo")
    private TipoContrato tipo;

the thing is, it includes underscore. Elasticsearch by default uses the standard analyzer which stores it and searches for it as one word. So, i.e. searching for ‘directa’ would not produce any results, but searching for ‘adjudicacion_directa’ would.

First you should enable http access to elasticsearch on your jhipster project to test if you’re getting results with a simple request, i.e using curl

curl -XPOST 'localhost:9200/contrato/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool" : {
      "should" : [
        { "match" : { "tipo" : "directa" } }
      ]
    }             
  }                                         
}
'

to get the results we’re expecting we need to change the analyzer that’s being used to index the field. We do this by changing the mapping. You could change it by using the REST api, and then reindexing your data. In development, we can reconfigure our mapping and then just do a mvn clean to regenerate it all.

Let’s change the mapping in our entity (we just need to add an annotation).

    @Enumerated(EnumType.STRING)
    @Column(name = "tipo")
    @Field(type = FieldType.String, analyzer = "simple")
    private TipoContrato tipo;

now, the results that came back from the curl request were fine. But the results from the search box didn’t. We had to include a custom search for it to work, cause the more general search doesn’t do a full text search apparently i.e. if you open in a new tab the url http://localhost:9200/contrato/_search?q=directa it doesn’t work but if you include the field it works http://localhost:9200/contrato/_search?q=tipo:directa

public interface ContratoSearchRepository extends ElasticsearchRepository<Contrato, Long> {

    @Query("{\n" +
        "  \"query\": {\n" +
        "    \"bool\" : {\n" +
        "      \"should\" : [\n" +
        "        { \"match\" : { \"_all\" : \"?0\" } },\n" +
        "        { \"match\" : { \"tipo\" : \"?0\" } }\n" +
        "      ]\n" +
        "    }             \n" +
        "  }                                         \n" +
        "}")
    Page<Contrato> buscarContrato(String query, Pageable page);

}

sources:
http://www.baeldung.com/spring-data-elasticsearch-tutorial
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html
https://stackoverflow.com/questions/31837546/elasticsearch-splitting-words-on-underscore-search-founds-nothing
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html
https://docs.spring.io/spring-data/elasticsearch/docs/3.0.2.RELEASE/api/

Anuncios

netbeans – Error package javax.validation.constraints does not exist

I’ve just upgraded to netbeans 8.2. I imported my previous settings from 8.1 when it asked me to do so. When I opened a previous project it throw me an error at compilation time complaining that I have missing the package javax.validation, at first I thought I had to reconfigure the jdk default home for netbeans (file [netbeans_dir]/etc/netbeans.conf) since it was choosing my os default open-jdk. But it had nothing to do with this.

You need to install the EJB and EAR plugin for it to work properly.

If you happened to have the plugin installed and still got the error above, it could be the application server you are using. In my case i configured the project to run on payara 173 which renamed the file bean-validator.jar to validation-api.jar to follow conventions, but netbeans 8.2 didn’t update the library path. A quick solution is to copy the file validation-api.jar in {payara-home}/glassfish/modules and name it bean-validator.jar.

sources:
https://groups.google.com/forum/#!topic/payara-forum/GVzQk2twHGM

Java 8 – Convert collection of objects to another type with streams

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

netbeans – it doesn’t start in ubuntu

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

Java – Instalar Glassfish en Ubuntu Server 14.04

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

SmartGWT – Validación dependiente (dependant validation)

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

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:
Java Build Tools: Ant vs Maven vs Gradle