Simple service to get gravatar avatars
Gravatar is a wordpress service allowing you to get an avatar URL from an email. If the person is not registered or doesn't have set up an avatar yet you will get a default one.
The strength of gravatar logic is to let you compute the URL from the email and avoid you to do any request to get the user profile or equivalent like most of these services.
Concretely it means you get an avatar management which is "local" on your server. Cons of that logic is, of course, you rely on an external website so gravatar.com needs to be accessible from your application (client side). But this is generally not a blocker.
Write a Java Gravatar Service
Gravatar logic is simple: take the mail, lowercase it, hash it with a MD5 and use the hexa representation of this. Then just use this value as a placeholder in the gravatar url.
This is the basic usage. You can also configure some behaviors like the icon size (avoid some css or client configuration and optimize the bandwidth if you have a list of avatars on your page) and the default icon (what to show if you the user doesn't have a gravatar - an identicon (generated from the mail), retro icon (generated from the mail), default gravatar one etc...).
These parameters are just query parameters in the gravatar url like size for the size and d for the default icon (note you can use 404 to get a HTTP response with a status code of 404 is missing).
Concretely a service in java will look like:
import org.apache.deltaspike.core.api.config.ConfigProperty;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@ApplicationScoped
public class GravatarService {
@Inject
@ConfigProperty(name = "app.gravatar.url", defaultValue = "https://www.gravatar.com/avatar/%s?d=%s&size=%d")
private String url;
@Inject
@ConfigProperty(name = "app.gravatar.icon.default", defaultValue = "identicon")
private String defaultIconType;
@Inject
@ConfigProperty(name = "app.gravatar.size.default", defaultValue = "40")
private Integer defaultSize;
public String computeGravatarUrl(String mail, int size, String defaultType) {
return String.format(
url,
hash(mail),
defaultType == null ? defaultIconType : defaultType,
size > 0 ? size : defaultSize);
}
private String hash(String mail) {
try {
final MessageDigest md = MessageDigest.getInstance("MD5");
final byte[] array = md.digest(mail.getBytes("CP1252"));
final StringBuilder sb = new StringBuilder();
for (final byte b : array) {
sb.append(Integer.toHexString((b & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString();
} catch (final NoSuchAlgorithmException | UnsupportedEncodingException e) {
throw new IllegalArgumentException(e);
}
}
}
Using this kind of service (replace deltaspike by @Value and you almost get the spring equivalent) will allow you to get a gravatar url for any mail, in any size and with any default.
The logic is really just about computing the hash representing the user in the URL and replacing it in a template.
Caching or not caching?
You would be using a remote service to get the avatar URL you would probably add JCache to cache the avatar url:
import org.apache.deltaspike.core.api.config.ConfigProperty;
import javax.cache.annotation.CacheDefaults;
import javax.cache.annotation.CacheResult;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@ApplicationScoped
@CacheDefaults(cacheName = "com.github.rmannibucau.gravatar")
public class GravatarService {
// config as before
@CacheResult
public String computeGravatarUrl(final String mail, final int size, final String defaultType) {
// as before
}
}
The only difference is to @CacheResult and use the default key - composed of all parameters - to ensure a same mail can get different size and defaults depending the context.
Does it worth it?
If you run it you will get a 0ms execution for all computation so your service is fast....but if you remove the caching you will get a 0ms execution too since MD5 is a very fast computation, in particular on small string like mails.
Conlusion is you don't need any caching for gravatar which makes it even simple. Because even if the code to cache the result is easy to use, it implies you need to handle your cache: which size, do you evict data and if so on which criteria? etc... All these questions are not needed in practise for such a computation so it doesn't worth to use any cache there until you add some logic in the computation like email retrieval from a database for instance (if you pass username instead of mail to the method).
Conclusion
Gravatar provides a ready to use and very fast way to give an avatar to your application users. It doesn't require any caching and is really smooth to implement (in any language actually).
However keep in mind this relies on a public website so you can need to revise this choice is you write an internal application. Common fallbacks for such applications are to reuse an internal github, jira, or any company wide user management. This last case can however imply to use some caching to avoid to issue some request for each user and each page. A common alternative will be to build a local (your application) user profile copying the avatar url and checking it from time to time, but this is likely the same as using JCache with a CacheLoader/CacheWriter but in a more custom way ;).
From the same author:
In the same category: