Tag Archives: Wicket

Publicado en : Informática

These days I’m dealing with Apache Wicket and RSS, trying to find a nice way to create a syndication feed that serves part of the content that users can view in the browser (so the content of the articles is HTML).

The mentioned style does not refer here to the embedded HTML (the one within the <content> section of the <entry>s) but to the <content>, <description>, <channel>… tags themselves).

To generate the RSS content I’ve used a trick that simulates a request to the server, leading Wicket to go through the whole request cycle and to render the HTML, which you finally get into a String variable. But that’s a (-n important, I know) matter of another post. By now, let’s just assume that we have a way to get that HTML content, or simply ignore that the content of the articles is HTML.

Well, if you have ever played with Rome you’ll know that, after creating your entries, the “end product” you get is a Feed instance. That’s our entry point. Let’s suppose that we want to serve that feed in a URL like, for instance, http://myserver.com/feeds/myfeed. As when serving JSON, the solution involves creating a custom implementation of IRequestTarget that writes the correct output and content type.

When extending IRequestTarget we must override the respond(RequestCycle requestCycle) method. And it’s there where we must do all the “magic”. Let’s assume that its constructor receives a Feed instance as parameter, and it will keep reference to it as a private variable. The first thing we do is to set the character encoding and the content type, to let the clients to recognize what kind of content they are fetching. Remember, once you have the Feed instance, serving RSS is the same as serving a simple XML. To style the feed, you’ll have to have a CSS or XSL somewhere that are the RSS stylesheets. We will write the RSS processing instructions that will make readers to include those stylesheets and apply them to the feed. For that we must use the WireFeedOutput instead of the common SyndFeedOutput (as I read in http://cephas.net/blog/2006/08/30/xsl-css-processing-instructions-using-rome/). Finally we write to the response output stream, obtained from the Wicket Response) and remember to bind the session if you need to.

public class RSSRequestTarget implements IRequestTarget {

 private SyndFeed feed;

 public RSSRequestTarget(SyndFeed feed) {
   this.feed = feed;
 }

 @Override
 public void respond(RequestCycle requestCycle) {
   requestCycle.getResponse().setCharacterEncoding("UTF-8");
   requestCycle.getResponse().setContentType("text/xml; charset=UTF-8");
   try {
     Writer writer = new OutputStreamWriter(requestCycle.getResponse().getOutputStream());
     WireFeedOutput feedOutput = new WireFeedOutput();
     Document doc = feedOutput.outputJDom(this.feed.createWireFeed());

     // create the XSL processing instruction
     Map<String, String> xsl = new HashMap<String, String>();
     xsl.put("href", "http://myserver.com/xsl/rss.xsl");
     xsl.put("type", "text/xsl");
     xsl.put("media", "screen");
     ProcessingInstruction pXsl = new ProcessingInstruction("xml-stylesheet", xsl);
     doc.addContent(0, pXsl);
<pre>     // create the CSS processing instruction
     Map<String, String> css = new HashMap<String, String>();
     css.put("href", "http://myserver.com/css/rss.css");
     css.put("type", "text/css");
     css.put("media", "screen");
     ProcessingInstruction pCss = new ProcessingInstruction("xml-stylesheet", css);
     doc.addContent(1, pCss);
</pre>
// response
 XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
 outputter.output(doc, writer);
 } catch (IOException e) {
 e.printStackTrace();
 } catch (FeedException e) {
 e.printStackTrace();
 }
 if (MyAppSession.get().getId() == null) {
 MyAppSession.get().bind();
 }

}

So, to use it in a WebPage, extend it as you’re used to do in Wicket, and at some point in the Page constructor, tell it to use our new IRequestTarget implementation (don’t forget to establish that we don’t need associated markup):

 public MyFeedPage extends WebPage {

  public MyFeedPage(PageParameters pageParameters) {
    [...]
    SyndFeed feed = new SyndFeedImpl();
    [...]
    getRequestCycle().setRequestTarget(new RSSRequestTarget(feed));
  }

  @Override
  public boolean hasAssociatedMarkup() {
    return false;
  }
}

Finally, in the init() method of your WebApplication class, mount the feed in your desired URL:

  [...]
  mountBookmarkablePage("/feed/myfeed", XXXPage.class);
  [...]

If you look at the generated feed you’ll see that the first lines look something like:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="http://myserver/xsl/rss.xsl"?>
<?xml-stylesheet type="text/css" media="screen" href="http://myserver/css/layout.css"?>

that are the processing instructions that make it possible to style your feed contents.

Please remember that most of web browsers will somewhat ignore these styles, but not all of them. And there are some RSS client applications that apply the styles when displaying them (think of Feedburner feeds viewer).

As I said, in my case I’m serving HTML content, which I obtain mock-mocking the Wicket request cycle internally. I’ll try to publish something about it.

Post to Twitter Post to Facebook

Publicado en : Informática

Since this blog is about foo and bar, now I’ll talk a little about bar.

Today I’ve been dealing with Wicket and JSON services, and I noticed that the JSON responses served from the framework were not correctly encoded (Spanish characters like ‘ó’ were encoded as ‘�’ and so on).

Here it is the (old) code of my custom IRequestTarget implementation, which I use in my web services to tell Wicket to respond using JSON instead of the default RequestTarget:

public class JSONRequestTarget implements IRequestTarget {

	private JSON response;

	public JSONRequestTarget(JSON response) {
		this.response = response;
	}

	@Override
	public void detach(RequestCycle requestCycle) {
		// Empty on purpose
	}

	@Override
	public void respond(RequestCycle requestCycle) {
		requestCycle.getResponse().setCharacterEncoding("UTF-8");
		requestCycle.getResponse().setContentType("application/json;");
		requestCycle.getResponse().write(this.response.toString());
		if (MeteosixSession.get().getId() == null) {
			MeteosixSession.get().bind();
		}
	}

}

As you can see, the character encoding is supposed to be correctly set in line #16, as well as the Content-Type in line #17. Inexplicably, even while Firebug confirmed that the returned headers were OK, the characters where badly encoded. What’s the solution?

You have to set the Content-Type to “application/json; charset=UTF-8″, replacing the line #17 with the following:

		requestCycle.getResponse().setContentType("application/json; charset=UTF-8");

This way you’ll receive in the client the JSON object with the correct Character Encoding and the correct Content-Type. I hope this can help anyone in the same situation to save some time google-ing for a solution.

Post to Twitter Post to Facebook

Publicado en : Android Informática

En mi primer post serio voy a hablar de una de las aplicaciones que desarrollé para Android y de los planes de futuro que hay para ella.

Hace ya unos cuantos meses que publiqué Android Roulette, un chat aleatorio para el operativo de Google. La verdad es que la repercusión superó con creces las expectativas, llegando en poco más de 2 meses a las 7000 descargas.

Detalle de Android Roulette en el Market

 

Probablemente lo primero que llame la atención de la captura que acabo de poner es la baja puntación y el porcentaje de instalaciones activas (sólo un 11%). La razón, que no la excusa, es que el servidor de la aplicación a través del cual los clientes encuentran compañero de chat y chatean (por cierto, detalle importante, implementado en Java con Apache Wicket) estaba alojado en un primer momento en una máquina de un conocido sin nombre de dominio, con lo cual los clientes (la aplicación Android) apuntaban directamente a una IP. En cuanto perdí la posibilidad de seguir alojando la aplicación del server allí tuve que cambiar de alojamiento, con el consiguiente cambio de IP, y por consiguiente todo aquel que tenía la aplicación instalada y que no actualizó de repente vio cómo ésta dejaba de funcionar. Hubo dos cambios de hosting como este, y al tercero… murió. Actualmente Android Roulette no tiene alojamiento a.k.a. no existe.

¿Por qué no la subes a un alojamiento Java decente? Sí, evidentemente ya no habría ese problema. Además los hay buenos. Pero son caros (no quería subirla al App Store o similares). El detalle de que estuviese hecho en Java conlleva un aumento de precio en servicios de hosting. Solución: lo he estado pensando, y como sí tengo un hosting que me permite aplicaciones en PHP, he decidido migrar el servidor a PHP. Quizás no sea un lenguaje bonito, pero sí cómodo en mi opinión, barato, y pese a lo que diga alguna gente funciona bien (¿te suena facebook?). Y dado que el server no tiene tampoco mucha miga (hay que encargarse de sincronizar a los usuarios que se conectan, y en principio se puede tirar contra una base de datos… si el tema funciona, habrá que pensar en algo más escalable, tipo memcached o algún gestor no-sql -sería todo un éxito tener que hacerlo!).

Pantalla de Android RoulettePantalla de Android Roulette

Actualizaré el cliente, intentaré difundir la “noticia” para que la gente que ya la tenga instalada actualice y a ver si vuelve a pegar un boom de descargas, o al menos de uso. La idea es buena, yo mismo pasaba el rato chateando, y creo que a la gente le gusta… si funciona. La interfaz es sencilla e iba bastante rápida y fluída. Así que empezaré en cuanto tenga algo de tiempo, que últimamente está la cosa apretada, pero espero no tardar mucho.

Post to Twitter Post to Facebook