Java | Customs Bean Validators for WebServices.

Ya todos conocen los mecanismos para validar POJOs que provee JEE, para el que no tenga conocimiento puede ver la especificación de la primera versión aquí y la versión 1.1 aqui:

La idea es que mediante anotaciones se puedan definir las validaciones a realizar, ademas se provee un grupo de validaciones básicas pero muy útiles. En el caso de que ese grupo no cumpla nuestros requerimientos se pueden hacer validaciones a medida y eso es justamente una de las cosas que voy a mostrar en este POST.

Crear un validador custom.

Para crear un validador personalizados se deberán crear dos clases.

  • La @interfaz (anotación) que define la anotación, su nombre, parámetros, donde puede ser usada, etc.
  • La implementación del validador: Es propiamente el código que valida los atributos a los que se les anote con dicha anotación.

La interfaz, podría recibir parámetros como se muestra a continuación y luego el mismo estará disponible en la implementan de la validación.

La @interfaz quedaría definida así.


@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = CustomValidatorImpl.class)
@Documented
public @interface CustomValidator {

   String message() default "ErrorMessage Custom Validator";

   Class<?>[] groups() default {};

   Class<? extends Payload>[] payload() default {};

   long value();

}

La implementan tomara el valor definido en la @interfaz  como el valor mínimo para el cual se deberá validar.

public class CustomValidatorImpl implements ConstraintValidator<CustomValidator, Long> {

  private long min;

  @Override
  public void initialize(CustomValidator constraintAnnotation) {
     this.min = constraintAnnotation.value();
  }

  @Override
  public boolean isValid(Long object, ConstraintValidatorContext constraintContext) {

    if (object == null) {
       return false;
    }
    return object > min;
  }
}

Luego si queremos utilizar la nueva validación realizamos lo siguiente:


public class Car {

    private String marca; 
    private String modelo;
   @CustomValidator(2) 
    private long puertas;
    @CustomValidator(2) 
    private long ventanas;

   ..............

Interceptor para validar parámetros de entrada ( por ejemplo en WebServices SOAP)

Si el entorno donde se están usando los POJOs, no es un entorno administrado que valide automáticamente las anotaciones, siempre podrán validarlas de forma explicita.

Para facilitar dicha tarea, voy a crear un Interceptor que permita validar los parámetros antes de ejecutar la acción de un WebService

Creamos el Interceptor:

public class ValidationInterceptor {

 @AroundInvoke
 public Object intercept(InvocationContext context) throws Exception {

  
   for (Object param : context.getParameters()) {
     ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
     Validator validator = factory.getValidator();
     Set<ConstraintViolation<Object>> constraintViolations = validator.validate(param);
     for (ConstraintViolation<Object> viol : constraintViolations) {
       System.out.println("ERROR::::" + viol.getMessage() + " property:" + viol.getPropertyPath());  
      }
   } 
   Object result = context.proceed();
   System.out.println("ValidationInterceptor - Logging AFTER calling method :" + context.getMethod().getName());
   return result;
 }
}

Definimos el Interceptor por ejemplo en un WebService SOAP:

@WebService(serviceName = "BeanValidatonWs")
@Interceptors(ValidationInterceptor.class)
public class BeanValidatonWs {
    .....................

El código de ejemplo lo encuentran en mi cuenta de Github: aqui

PrimeFaces PickList + RemoteCommand Example

Este ejemplo muestra cómo combinar el componente PickList de PrimeFaces con el componente remoteCommand.
La idea es procesar una lista de acciones, de a uno por vez, e ir mostrando el avance al usuario.

Lo primero definir el markup de la vista.

Definimos un growl y un dialogo, para mostrar el progreso y notificar del procesamiento respectivamente.

<p:growl id="msg" showDetail="false" autoUpdate="true"/>
<p:dialog modal="true" widgetVar="statusDialog" header="Status" draggable="false" closable="false">
 <p:graphicImage value="/design/ajaxloadingbar.gif"/>
</p:dialog>

Luego el componente p:pickList

<p:pickList id="pickList" value="#{pickCtrl.list}" var="elem" itemLabel="#{elem}" itemValue="#{elem}" />

Y por ultimo, el commandButton para iniciar el procesamiento y un remoteCommand para invocarlo mediante js desde el Bean.

<p:commandButton actionListener="#{pickCtrl.process}" value="process" onstart="statusDialog.show();" update="@(form)"/>
<p:remoteCommand actionListener="#{pickCtrl.process}" name="processCommand" update="@(form)"/>

Del lado del servidor vamos a ejecutar la acción y si aun quedan elementos por procesar volveremos al cliente para actualizar la lista e invocamos nuevamente

El vídeo de ejemplo lo pueden ver aquí y el código aquí.

Java – Cliente WS a partir de un WSDL

Para crear el cliente Java para un servicio se requiere de lo siguiente:

  1. El archivo WSDL que describe el servicio a consumir.
  2. Una instalación de JDK con una versión acorde a la cual se utilizara para compilar.
  3. La ruta donde se desean crear las clases.
  4. El paquete Java en el cual estarán las clases.  Ej: com.pepe.lala.wsdl.client

Luego que se tengan bien identificado los puntos listados anteriormente, realizamos lo siguiente:

  1. Abrimos una consola cmd en modo administrador. ( para no tener problema de permisos)
  2. Nos movemos hasta la carpeta bin de la instalación de la JDK a utilizar
    •  Ej: cd c:\Program Files\Java\jdk1.6.0_45\bin
  3. Ejecutamos el siguiente comando: wsimport.exe  -s ${dest} -p ${pkq} -keep -Xnocompile  ${wsld} donde
    • ${dest}    => Ruta donde se crearan las clases.
    • ${pkq}     => Paquete Java donde seran creadas las clases.
    • ${wsdl}   => Ruta absoluta al archivo WSDL.
  4. Si es necesario movemos las clases generadas a donde se requiera ( ${dest} ya puede contener la ruta deseada ahorrándonos este paso)
  5. El comando wsimport  genera algunos constructores en la clase que implementa el Servicio, si alguno da problemas de compilación en su ambiente, los pueden eliminar sin problemas.

 

Ejemplo:


c:\Program Files\Java\jdk1.6.0_45\bin&gt;wsimport.exe -s C:\trabajo\eclipse\WorkSpaceLuna\PAYware-WEB -p com.pepe.lala.wsdl.client -keep -Xnocompile c:\tarjeta.wsdl

parsing WSDL...

generating code...

Android – Check internet connection

Is common on a mobile applicatin that need internet connection to work, start with a connection check, and in case that the connection isn´t ok, encourage the user to check it.

Android provided a network handler to check the connection state, but this will not assure that the device could connect to your server. The state only indicate the connection status and not if the connection is healthy or not.

I wrote a simple class that check the internet connection ( using the connection status) and gives the option to make a http request to check if device has really a internet access.

I will add the code here, maybe someone out there could use it. Remember call it in an asynchronous task.

package com.dima.pencuy.utils.connection;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

public class ConnectionDetector {

    private static final String DEFAULT_PING_URL = "http://www.google.com";
    private static final String USER_AGENT_HEADER = "User-Agent";
    private static final String USER_AGENT_HEADER_VALUE = System.getProperty("http.agent");
    private static final String CONNECTION_HEADER = "Connection";
    private static final String CONNECTION_HEADER_VALUE = "Close";
    private static final int TIMEOUT = 1500;
    private static final String LOG_TAG = "ConnectionDetector";

    private Context context;
    private String urlToPing;
    private boolean ping;

    public ConnectionDetector(Context context, String... urlToPing) {
        this.context = context;
        if (urlToPing.length > 0) {
            this.urlToPing = urlToPing[0];
            this.ping = true;
        } else {
            this.ping = false;
        }
    }

    public ConnectionDetector(Context context,boolean pingCheck) {
        this.context = context;
        this.ping = pingCheck;
        if(this.ping){
            this.urlToPing = DEFAULT_PING_URL;
        }
    }

    public boolean isConnected() {
        ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo[] info = connectivity.getAllNetworkInfo();
            if (info != null)
                for (int i = 0; i < info.length; i++)
                    if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                        if (ping) {
                            return pingServer();
                        } else {
                            return true;
                        }
                    }

        }
        return false;
    }

    public boolean pingServer() {
        try {           
            HttpURLConnection urlConnection = (HttpURLConnection) (new URL(urlToPing).openConnection());
            urlConnection.setRequestProperty(USER_AGENT_HEADER, USER_AGENT_HEADER_VALUE);
            urlConnection.setRequestProperty(CONNECTION_HEADER, CONNECTION_HEADER_VALUE);
            urlConnection.setConnectTimeout(TIMEOUT);
            urlConnection.connect();
            return (urlConnection.getResponseCode() == 200);
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error checking internet connection", e);
        }
        return false;
    }

}


JBoss Instalación en modo domain.

Jboss permite hace ya unas cuantas versiones la instalación en modo Domain, permitiendo administrar un grupo de instancias de forma sencilla.

En cada instalación se debe evaluar la cantidad de instancias en modo Host que se desean utilizar y la cantidad de instancias en modo Slave que se levantaran en cada uno de los Hosts, por lo general esta información se obtiene a partir de las estimaciones de usuarios y llamadas concurrentes que se deberán soportar.

Comúnmente se configura un Host por servidor (físico o virtual) pero podría levantarse más de un Host en cada servidor, si el mismo cuenta con varias IPs.

Los pasos siguientes detallan la configuración a realizar para una infraestructura con dos Host (cada uno en un servidor distinto) con tres instancias/servers por HOST, todo agrupado en dos grupos.
Cada grupo será administrado de forma independiente, permitiendo desplegar las aplicaciones automáticamente en todos los servidores del grupo, así como configurar propiedades de cada uno de ellos en un único archivo.

Supongamos entonces que contamos con los siguientes servidores

  • Servidor 1 con IP: 10.64.70.16 el cual contendrá el Host-1 y además será el encargado de la administración, por tanto será el domain-controller.
  • Servidor 2 con IP: 10.64.70.170 el cual contendrá el Host-2, el mismo se conectara al domain-controller del Host-1.

El diagrama de la instalación a realizar:

diagrama

 

Instalación de JBoss

La instalación de los servidores no difiere en nada al modo standalone, se deberán copiar los archivos de JBoss como si fuera a realizarse una instalación en modo standalone y luego configurar los servidores y grupos a utilizar.

Configuración de cada HOST

Para la conexión de los distintos nodos esclavos con el domain controller será necesario contar con un usuario administrador. Para crearlo localice el script add-user.bat|sh en la carpeta JBOSS_HOME/bin del servidor 1 (el que oficiara como domain-controller).
Cree un nuevo usuario en el Realm de nombre ManagementRealm, en el último paso el script consultara por lo siguiente.

Is this new user going to be used for one AS process to connect to another AS process e.g. slave domain controller?
yes/no? y
To represent the user add the following to the server-identities definition

Contestar “yes” y copiar el tag , para su utilización a posterior, recordar el nombre de usuario elegido. Para ejemplificar supongamos fue creado el usuario “admin”.

Configurar archivo host.xml (JBOSS_HOME/domain/configuration/host.xml)

  • Configurar el nombre del host correcto para cada servidor dentro del tag host como se muestra a continuación
 <host name="[host1|host2]" xmlns="urn:jboss:domain:1.4">
  • Para el Host-1, configurar las interfaces dentro del tag <interfaces> colocando la ip en la cual se asociara la consola de administración
<interfaces>
   <interface name="management">
      <inet-address value="${jboss.bind.address.management:10.64.70.16}"/>
   </interface>
   <interface name="public">
      <inet-address value="${jboss.bind.address:10.64.70.16}"/>
   </interface>
....
  • En el Host-1 configurar el tag <domain-controller>.
<domain-controller>
       <local/>
</domain-controller>
  • En el Host-2 configurar el tag <domain-controller>
<domain-controller>
<remote host="10.64.70.16" port="${jboss.domain.master.port:9999}" username="admin" security-realm="SlaveRealm"/>
</domain-controller>
  • Definir un nuevo Realm utilizando la clave que se obtuvo en la última pregunta del script de creación de usuarios en el Host-2.
<security-realm name="SlaveRealm">
<server-identities>
		<secret value="VG8kJCRUYTQ=" />
	</server-identities>
</security-realm>

Configuración de Grupos

La configuración de los servers y sus grupos se debe realizar en cada uno de los HOST, la misma se realiza en el archivo host.xml. Más adelante configuraremos  los grupos en si y sus propiedades.

Para el ejemplo planteado:

  • Host-1
<servers>
<server name="acq-three" group="group_2" auto-start="true">
		<socket-bindings port-offset="1000"/>
       </server>
<server name="issr-two" group=" group_1" >
		<socket-bindings port-offset="2000"/>           
       </server>
	<server name="issr-three" group="group_1" auto-start="true">
		<socket-bindings port-offset="3000"/>           
       </server>
</servers>
  • Host-2
<servers>
        <server name="acq-one" group="group_2" auto-start="true">
		<socket-bindings port-offset="1000"/>
        </server>
	 <server name="acq-two" group="group_2" >
		<socket-bindings port-offset="2000"/>           
        </server>
	 <server name="issr-one" group="group_1" auto-start="true">
		<socket-bindings port-offset="3000"/>           
        </server>
</servers>

Configuración de Perfiles

La definición de los grupos y los perfiles utilizados solo es necesaria en el host que juega el rol de domain-controller, el resto de los esclavos obtienen la configuración del domain-controller al momento de iniciar y registrarse en el domain.

Para la instalación planteada debemos alterar el archivo domain.xml dentro del Host-1.

<server-groups>
	<server-group name="group_1" profile="default">
				<jvm name="default">
					<heap size="500m" max-size="500m"/>
					<permgen max-size="256m"/>
				</jvm>
				<socket-binding-group ref="full-sockets"/>            
			</server-group>
			<server-group name="group_2" profile="default">
				<jvm name="default">
					<heap size="500m" max-size="500m"/>
					<permgen max-size="256m"/>
				</jvm>
				<socket-binding-group ref="full-sockets"/>
	</server-group>
</server-groups>

Como se puede ver en la configuración anterior, se está haciendo referencia a un profile llamado default. El mismo esta definido al comienzo del archivo, y se deberá definir en el los datasources y eñ resto de las configuraciones necesarias para el grupo.

Jboss – Application Logging in different file.

Sometimes we need to separate the log of each application running on the same server into different files.

On Jboss AS 7 or a newer version you can achieve that very easy.
You have only to modify the logging subsystem section inside the standalone.xml or domain.xml file.

First we define a file handler for the app.

<periodic-rotating-file-handler name="FILE_APP">                
   <formatter>
     <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
   </formatter>
   <file relative-to="jboss.server.log.dir" path="applog.log"/>
   <suffix value=".yyyy-MM-dd"/>
   <append value="true"/>
</periodic-rotating-file-handler>

Then define all the packages names you want to log to the file, like this

 <logger category="com.MY-APP-PACKAGE" use-parent-handlers="false">
     <level name="INFO"/>
     <handlers>
        <handler name="FILE_APP"/>
     </handlers>
 </logger>  

If use-parent-handlers=»true» the log will be on both files, server.log and applog.log

Finally add the handler to the root-logger.

<root-logger>
  <level name="INFO"/>
  <handlers>
    <handler name="CONSOLE"/>
    <handler name="FILE"/>
    <handler name="FILE_APP"/>
  </handlers>
</root-logger>

The complete logging subsystem section

        <subsystem xmlns="urn:jboss:domain:logging:1.2">
            <console-handler name="CONSOLE">
                <level name="INFO"/>
                <formatter>
                    <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
                </formatter>
            </console-handler>
            <periodic-rotating-file-handler name="FILE">
                <formatter>
                    <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
                </formatter>
                <file relative-to="jboss.server.log.dir" path="server.log"/>
                <suffix value=".yyyy-MM-dd"/>
                <append value="true"/>
            </periodic-rotating-file-handler>
            <periodic-rotating-file-handler name="FILE_APP">                
                <formatter>
                    <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
                </formatter>
                <file relative-to="jboss.server.log.dir" path="applog.log"/>
                <suffix value=".yyyy-MM-dd"/>
                <append value="true"/>
            </periodic-rotating-file-handler>
            <logger category="com.arjuna">
                <level name="WARN"/>
            </logger>
            <logger category="org.apache.tomcat.util.modeler">
                <level name="WARN"/>
            </logger>
            <logger category="sun.rmi">
                <level name="WARN"/>
            </logger>
            <logger category="jacorb">
                <level name="WARN"/>
            </logger>
            <logger category="jacorb.config">
                <level name="ERROR"/>
            </logger>            
            <logger category="com.MY-APP-PACKAGE" use-parent-handlers="false">
                <level name="INFO"/>
                <handlers>
                    <handler name="FILE_APP"/>
                </handlers>
            </logger>         
            <root-logger>
                <level name="INFO"/>
                <handlers>
                    <handler name="CONSOLE"/>
                    <handler name="FILE"/>
                    <handler name="FILE_APP"/>
                </handlers>
            </root-logger>
        </subsystem>

JBoss – Dump Web Service Messages

Muchas veces tenemos errores difíciles de encontrar cuando estamos trabajando con WebServices – SOA, uno de los más comunes es que el PARSER no logre armar el mensaje y no tengamos forma de ver cuál es el mensaje que recibimos, ya sea porque lo envía un tercero o por otro motivo.
Hoy me enfrente a exactamente este problema, y por tal motivo me puse a investigar de qué forma podría hacer un DUMP del mensaje en crudo antes de que el PARSER intente armarlo.
Al final era tan sencillo como agregar una propiedad dentro del archivo standalone.xml y reiniciar el servidor.

<system-properties>
  	<property name="org.apache.cxf.logging.enabled" value="true"/>
</system-properties>

Espero le sea de utilidad a alguien mas.

Mock Service with SOAP-UI.

Everyone that has had to develop a SOAP Web Service client at least on one time, surely suffered the problem to test it.

Yesterday I realize that more than the midle of the people working with me didn´t know about the SOAP-UI funcionality to develop a WebService Mock, using the WSDL.

So I recorded a video to show how it work, the linke here

Primefaces Extensions: New component to generate QR Codes

Yesterday I finished the development of a new component called pe:qrCode. The component enables you to dynamically generate QR codes. You can choose between a lot of options like rendering mode, color, size and more.

For the background of the component, I made use of javascript plugins jQuery.qrcode (code here)

The demo is like the next image:

qrcode component

Give it a try in the Primefaces-Ext Showcase

Collection.emptyList() + java.lang.UnsupportedOperationException

Es común utilizar el método estático emptyList() de la clase Collection cuando se requiere retornar una lista vacía del estilo List
Utilizando este método se gana en performance ya que el mismo no tiene el overhead de crear una nueva lista cada vez, sino que siempre devuelve la misma. Es por tal motivo que la lista es inmutable (no se puede modificar).
Por tanto cuando se usa algo del estilo:

  ret = Collections.<datatype>emptyList();

Hay que estar seguro de no querer luego modificarla, en caso de intentar realizar algo como:

  ret.add(elem);

Se obtiene una excepcion java.lang.UnsupportedOperationException en RUNTIME.

Mas referencias de la clase Collection:
http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html