viernes, 21 de enero de 2011

18-digit case-safe ID on Salesforce.com

Today while doing a small test to check a Salesforce's API client I noticed that several objects returned by the API, has IDs of 18 characters which I found strange since they are supposed to be 15 letters and numbers, according to the API's documentation.

For reference, an excerpt of the official documentation of salesforce:
ID Field Type

With rare exceptions, all objects in the API have a field of type ID that is named Id and contains a unique identifier for each record in the object. It is analogous to a primary key in relational databases...

ID fields in the Salesforce.com user interface contain 15-character, base-62, case-sensitive strings. Each of the 15 characters can be a numeric digit (0-9), a lowercase letter (a-z), or an uppercase letter (A-Z). Two unique IDs may only be different by a change in case.

With the aim of understanding why the ID returned by the API contain more than 15 characters did a little research and found the following:
Because there are applications like Access which do not recognize that 50130000000014c is a different ID from 50130000000014C, an 18-digit, case-safe version of the ID is returned by all API calls. The 18 character IDs have been formed by adding a suffix to each ID in the Force.com API. 18-character IDs can be safely compared for uniqueness by case-insensitive applications, and can be used in all API calls when creating, editing, or deleting data.

If you need to convert the 18-character ID to a 15-character version, truncate the last three characters. Salesforce.com recommends that you use the 18-character ID.

Conclusion.
So in essence, to prevent problems for those situations when case sensitive differences are not detected the API is returning 18-digits case-safe version of the ID.

Hope this is useful to any of you.

miércoles, 13 de octubre de 2010

Como usar Spring Validator en ColdFusion

Para usar esto debes haber configurado primero el javaloader 1.0 http://www.compoundtheory.com/javaloader/docs/ de tu aplicacion de coldfusion.

Para validar primero necesitamos un bean del modelo, usaremos para el ejemplo la clase Contact.java.

import javax.persistence.*;


import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Entity
@Table(name="Contacts")
public class Contact {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "contact_id")
private Long id;

@Size(max=50)
@Column(name="contact_name")
private String name;

@Size(max=100)
@Column(name="contact_email")
private String email;

public Contact(){
this.name = "";
this.email = "";
}

//getters and setters ...
}




Spring Framework nos da una interfaz de validacion fácil de usar y libre de contexto, asi que creamos un ContactValidator. Esta interfaz tiene dos métodos, support(Class) y validate(Oject, Errors). La referencia Object indica el contacto que vamos a validar, y Errors es una interfaz de springframework que guarda los errores si estos ocurren. Esto se explica mejor en el capitulo 5 de la referencia de Spring Framework.



ContactValidator.java





package com.admios.utils;

import org.springframework.validation.*;

import com.admios.model.Contact;


public class ContactValidator implements Validator {

private static String emailRegularExpression = "[a-zA-Z_]+.+@.+\\..+";

@Override
public boolean supports(Class<?> clazz) {
return Contact.class.equals(clazz);
}

@Override
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmpty(errors, "name", "You must provide a name for this contact.");

Contact cont = (Contact) target;
if (! cont.getEmail().matches(emailRegularExpression)){
errors.rejectValue("email", "Please provide a valid email address in the format user@domain.com (Display Name)");
}
}

public static String getEmailRegularExpression() {
return emailRegularExpression;
}
}




Ok, Vamos a usar el camino mas facil para hacer el llamado en ColdFusion, solo queremos enviar el contacto al servicio y recoger los errores, sin tener que lidiar con el metodo de validacion directamente.



En Util.java creamos un metodo estatico para validar el contacto y que nos traiga de vuelta los errores. BindException es una implementación de Errors.





package com.admios.utils;


import org.springframework.validation.BindException;
import org.springframework.validation.Errors;

import com.admios.model.Contact;

public class Util {

public static Errors validateContact(Contact contact){

ContactValidator validator = new ContactValidator();
Errors errors = new BindException(contact, "contact");
validator.validate(contact, errors);
return errors;
}
}




Una vez hecho esto, y haber sido probado con JUnit, podemos mover el servicio a la aplicacion de coldFusion.



check_contact.cfm





 <cfset lstLocalErrors = "">
<cfparam name="is_active" default="0">


<!-----------------------------------------------------------------------------
! Binding And Validation
!----------------------------------------------------------------------------->

<cfscript>
contact = server.javaloader.create("com.admios.model.Contact").init();
utilClass = server.javaloader.create("com.admios.utils.Util").init();

contact.setName(con_name);
contact.setEmail(con_email);

errors = utilClass.validateContact(contact);

</cfscript>

<cfif errors.getErrorCount() eq 0>

<!--------------------------------------------------------------------------
! Save, if no occurs errors.
!------------------------------------------------------------------------->


<cfinclude template="/includes/user/event/save_contact.cfm">
<cfelse>
<cfset lstErrorFields = "">
<cfscript>
errorName = errors.getFieldError("name");
errorEmail = errors.getFieldError("email");
</cfscript>

<!-------------------------------------------------------------------------
! error messages
!------------------------------------------------------------------------->

<cfif isDefined("errorName")>
<cfset lstLocalErrors = ListAppend(lstLocalErrors, errorName.getCode(),CHR(9))>
<cfset lstErrorFields = ListAppend(lstErrorFields, 'con_name')>
</cfif>

<cfif isDEfined("errorEmail")>

<cfset lstLocalErrors = ListAppend(lstLocalErrors, errorEmail.getCode(), CHR(9))>
<cfset lstErrorFields = ListAppend(lstErrorFields, 'con_email')>
</cfif>
<cfset lstErrors = ListAppend(lstErrors, lstLocalErrors, CHR(9))>
</cfif>




    Con errors.getFieldError("name") obtenemos el campo de error que validamos en ContactValidator.java





ValidationUtils.rejectIfEmpty(errors, "name", "You must provide a name for this contact.");




    Y lo mismo para el email.



El errorEmail.getCode() nos da el codigo para al propiedad a ser mostrada en la vista del usuario. Si el codigo no es encontrado en el archivo de properties, entonces el mismo "codigo" es devuelto.



Reference:



BindException



Errors



ValidationUtils



Validator



spring-framework-reference.pdf


miércoles, 6 de octubre de 2010

Extendiendo sus estilos CSS

A mediados del año pasado se dio a conocer un proyecto open source llamado Less CSS, el cual nos permite a los desarrolladores web agregar las tan deseadas variables, funciones y mixins a nuestras hojas de estilo. La implementación inicial se realizo en Ruby y luego fue llevada a distintos lenguajes.

Mi experiencia en .Net con .Less

Cuando decidí probar Less CSS estaba desarrollando una duplicación en Asp.Net MVC 2, y decidí utilizar la implementación llamada .Less para .Net. En el momento en que la utilice me decepcionó, la falta de soporte para las reglas de CSS3, reglas especificas para ciertos navegadores (-moz- para firefox o -webkit para Safari/Chrome) o soporte para los hacks para nuestro viejo compañero IE me hicieron dejar de utilizar este proyecto (Al momento de escribir este post tal parece que mejoraron .Less, valdría la pena darle un vistazo de nuevo, este sera tema de otro post).

¡Less.js a escena!

Un par de meses atrás leí acerca de una implementación de Less en JavaScript, la cual hace unos días atrás me decidí a probar. A mi parecer es la mejor implementación que he visto, además de ser desarrollada por el mismo creador de Less CSS, esta librería esta basada en Node.js y dice según su desarrollador ser 50 veces mas rápida que su contra parte de Ruby.

He probado desarrollar un CSS con less y me he enamorado de la facilidad con que extiendo mi CSS y mis habilidades. El tiempo de desarrollo de una hoja de estilo se ve reducido así mismo como su tamaño, esto se logra al usar mixins, que no es mas q usar una clase o función dentro de una regla. Pongamos un ejemplo común agregar esquinas redondeadas a un objeto. Comúnmente había que agregar como mínimo 3 lineas a cada juego de reglas, o crear una clase y agregarse la al objeto al momento de definirlo en html. Este proceso se reduce con Less, veamos el siguiente ejemplo:

.rounded_corners (@radius: 5px) {  
-moz-border-radius: @radius;
-webkit-border-radius: @radius;
border-radius: @radius;
}
#header { .rounded_corners; }
#footer { .rounded_corners(10px); }

Como pueden ver agregar fragmentos de código es muy fácil y se logra un ahorro en el tamaño del archivo al no repetir estas reglas en el #header y el #footer.

Esto sumado a la posibilidad de agregar variables, anidar reglas dentro de sus padres y muchas otras características hacen de esto una gran ayuda al momento de crear sus archivos CSS.

¡OK! Me convenciste, ¿cual es el catch?

No existe una deficiencia tan grande como para no darle una probadita a esta herramienta en alguno de sus proyectos, pero si existen algunos puntos que tomar en consideración:

  • Si el usuario no tiene activado Javascript Less.js no podra ejecutarse, por tanto todo el estilo que dependa de Less no se podrá ver.
  • El código no es interpretado del lado del servidor, asi que su usuario podrá ver el código de CSS con sus mejoras realizadas en Less
Y la mas Importante:
  • Se puede acostumbrar tanto a usar Less que después codificar en CSS plano le puede parecer obsoleto
Si desea probar este proyecto puede dirigirse a su página en GitHub y descargar la última versión.

lunes, 22 de marzo de 2010

Patrones de Diseño para interfaces de busquedas

Ultimamente he visto novedosos libros de diseño de interfaces. Existe este libro llamado Search Patterns: Design for Discovery, que tienen un sitio web para material adicional llamado searchpatterns.org.

Lo interesante del asunto es que searchpatterns.org tambien enlaza a Welie.com el cual contiene patrones adicionales para todo tipo de interfaz gráfica.

Voy a ver si para cuando tenga otro proyecto en Silverlight uso estos sitios para tomar ideas.