J’ai publié sur GitHub le code source d’une application Web Java très simple mais qui contient tous les éléments permettant de commencer à développer une “vraie” application Java pour Windows Azure. Il s’agit d’un projet Eclipse contenant les éléments suivants:

L’idée est de fournir aux développeurs Java quelque chose d’un peu “prêt à l’emploi” et qui ne nécessite pas d’aller réunir tous les éléments à la main…

Voici à quoi ressemble l’application au final:

image

Et voici quelques informations sur les différents composants de l’application.

Tout d’abord, la configuration Hibernate:

<!-- Database connection settings -->
<property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
<!-- Local database settings (e.g. SQL Express) -->
<property name="connection.url">jdbc:sqlserver://localhost:1433;databaseName=Chinook;</property>
<property name="connection.username">sa</property>
<property name="connection.password">Pass123!</property>
<!-- SQL Azure connection settings -->
<!--<property name="connection.url">jdbc:sqlserver://YOURSERVER.database.windows.net:1433;databaseName=Chinook</property>-->
<!--<property name="connection.username">YOURLOGIN@YOURSERVER</property>-->
<!--<property name="connection.password">YOURPASSWORD</property>-->
<!-- JDBC connection pool (use C3P0) -->
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.idle_test_period">60</property>
<property name="hibernate.c3p0.max_statements">100</property>
 

J’ai inclus deux configurations possible: “localhost” pour le développement, qui se fait typiquement avec une base SQL Express locale, et le modèle d’une configuration SQL Azure, avec les URL au bon format ainsi que le login qui doit suivre un format un peu spécifique (user@host).

J’ai également configuré un connection pool C3P0, qui me permet de positionner un “idle_test_period” à 60 secondes, nécessaire quand on passe sur SQL Azure, car l’infrastructure Windows Azure coupe automatiquement les connexions TCP non utilisées pendant plus de 60 secondes!

Le reste de la configuration est classique, j’ai modélisé trois classes (Album, Artist, Track) sur la base d’exemple Chinook que vous pouvez télécharger sur CodePlex.

J’ai ensuite une classe très simple, mais dont le but est de montrer que l’on peut bien accéder à SQL Azure, et également utiliser le Blob Storage Windows Azure pour y stocker des images.

public class AlbumService {
	protected static final String BLOB_HOST_NAME = "http://tcontepub.blob.core.windows.net/";
	protected static final String BLOB_CONTAINER_NAME = "ledzep";
	
	public List<DisplayAlbum> getAlbumsForArtist(String artistName) {
		List<DisplayAlbum> displayAlbums = new ArrayList<DisplayAlbum>();
		
    	Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    	
        session.beginTransaction();
		List albums = session.createQuery("from Album a where a.artist.name='" + artistName + "'").list();
        for (int i=0; i < albums.size(); i++) {
        	Album a = (Album)albums.get(i);
        	
        	String blobName = a.getTitle() + ".jpg";
        	String containerName = BLOB_CONTAINER_NAME;
        	String img = null;
        	
        	if (BlobUtil.blobExists(containerName, blobName)) {
            	img = BLOB_HOST_NAME + containerName + "/" + blobName;
        	}
        	DisplayAlbum da = new DisplayAlbum();
        	da.setTitle(a.getTitle());
        	da.setAlbumId(a.getAlbumId());
        	if (img != null) {
        		da.setCover(img);
        	}
        	displayAlbums.add(da);
        }
        session.getTransaction().commit();
        
        return displayAlbums;
	}
}

Ici, je fais une requête à l’aide d’Hibernate dans la base SQL pour trouver une liste d’albums correspondant à un artiste. Une fois les albums récupérés, je fais des requêtes vers le Blob Storage pour voir si j’ai un fichier JPEG portant le même nom (la photo de la couverture de l’album), et si oui je l’ajoute dans les objets qui me serviront à l’affichage. L’exemple est trivial, mais permet, dans la classe BlobUtil, d’illustrer l’accès au Blob Storage:

public class BlobUtil {
	  //protected static final String BLOB_HOST_NAME      = "http://blob.core.windows.net/";
	  //protected static final String AZURE_ACCOUNT_NAME  = "YOURACCOUNT";
	  //protected static final String AZURE_ACCOUNT_KEY   = "YOURKEY";
	  //protected static final boolean PATH_STYLE_URIS	= false;
	  protected static final String BLOB_HOST_NAME      = "http://127.0.0.1:10000/";
	  protected static final String AZURE_ACCOUNT_NAME  = "devstoreaccount1";
	  protected static final String AZURE_ACCOUNT_KEY   = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";
	  protected static final boolean PATH_STYLE_URIS	= true;
	  	  
	  public static boolean blobExists(String containerName, String blobName) {
		  BlobStorageClient storageClient = BlobStorageClient.create(
				  URI.create(BLOB_HOST_NAME),
				  PATH_STYLE_URIS,
				  AZURE_ACCOUNT_NAME,
				  AZURE_ACCOUNT_KEY);
		  
		  IBlobContainer container = storageClient.getBlobContainer(containerName);
		  
		  return container.isBlobExist(blobName);
	  }
}

On le voit ici, l’API est très simple: un appel à container.isBlobExist() permet de tester l’existence d’un Blob.

Les paramètres statiques sont par défaut configurés pour pointer vers l’émulateur de stockage qui tourne en local. Pour un déploiement dans Windows Azure, vous utiliserez l’autre série de paramètres, dans laquelle vous reprendrez le compte et la clef que vous trouverez dans le portail d’administration.

Enfin, une petite page JSP permet d’assembler le tout:

<jsp:useBean id="AlbumService" class="org.azurejava.sample.AlbumService" scope="page" />
<div id="albums">
<%
	List<DisplayAlbum> albums = AlbumService.getAlbumsForArtist("Led Zeppelin");
	Iterator<DisplayAlbum> i = albums.iterator();
	while (i.hasNext()) {
		DisplayAlbum a = i.next();
%>
	<div class="album">
		<div><%= a.getCover() != null ? "<img class=\"albumcover\" src=\"" + a.getCover() + "\">" : "" %></div>
		<div><%= a.getTitle() %></div>
	</div>
<%
	}
%>
</div>

Cette application peut parfaitement tourner dans un Tomcat standard installé sur votre machine. Vous n’avez pas particulièrement besoin de l’exécuter dans le cadre de l’émulateur Windows Azure.

Par contre, pour la déployer dans Windows Azure, il vous faudra la packager, et vous pourrez utiliser le Windows Azure Starter Kit for Java, ce qui fera l’objet d’un nouveau billet! :-)

Je vais certainement faire évoluer cet exemple en Java, donc suivez-le sur GitHub!