Syntax coloring

sexta-feira, 30 de setembro de 2011

Yet another Internet Explorer issue: Java applets created by JavaScript

In Cyclos, I've been working to implement support for printing in a local receipt printer.
We found the jZebra project which is a Java applet that prints in a receipt printer on the local computer.
So, as this is an optional feature, and will only be used by few users, we didn't want to load the applet on every page. Instead, only when the user clicks print, the applet tag is created and appended to the document with JavaScript (using document.createElement("applet") and friends).
Then, the usual sequence:
  • Test in Firefox: check.
  • Test in Chrome: check.
  • Test in Opera: check.
  • Find a computer running windows somewhere to test in Internet Exporer: fail.
Why I wasn't surprised?
When adding the applet through JavaScript, MSIE somehow doesn't makes the public applet methods visible for JavaScript. So, no .findPrinter(), no .append(), no .print(). 
Result? As this feature won't be used by most users, we decided to disable it on MSIE, at least until some workaround is found. ..

What a revange!

sábado, 24 de setembro de 2011

Atualizando o firmware do LG Optimus ME (P350) com VirtualBox no Linux

Eu comprei recentemente um celular LG Optimus ME (P350), que vem com o Android 2.2.2.
O problema é que ele vem com o firmware bem desatualizado 10a. Ele tem um bug que, ao tocar na tela, a cpu vai lá em cima... Emfim.
Baseei-me neste post para realizar o procedimento: http://www.sleetherz.com/2011/09/how-to-update-lg-optimus-p350-to-firmware-v-10c/
Mas tem um detalhe extra: Como não tenho o windows instalado (uso somente o Linux), e o software é só para windows, temos um probleminha. Mas, como nem tudo é perfeito, tenho um VirtualBox com um winxp pra esses casos... Então tá.

Atenção! Este procedimento foi o que eu fiz, e funcionou para mim. Não me responsabilizo caso dê algo errado...

Primeiro: Quando o telefone está em modo de emergência, ele é detectado pelo Linux como um modem. Assim, o kernel sobe o módulo cdc_acm, para poder utilizar o dispositivo. O problema é que se o Linux usa o dispositivo, não tem como ele ser usado pelo VirtualBox. Então, a primeira coisa a fazer é impedir o carregamento desse módulo. Edite o arquivo /etc/modprobe.d/blacklist.conf e adicione a seguinte linha:
blacklist cdc_acm. Depois que o procedimento terminar, você pode remover essa linha.

Segundo
: Tenha o VirtualBox com o Extension Pack instalado. Dê uma olhada na página de downloads: http://www.virtualbox.org/wiki/Downloads.

Agora, execute estas operações dentro da máquina virtual:

  1. O artigo no qual me baseei recomenda que o micro esteja desconectado da Internet. No VirtualBox, basta ir em Dispositivos > Adaptadores de Rede e desmarcar o Cabo conectado.
  2. Baixe o firmware em http://www.lg-phones.org/lg-optimus-me-firmwares-download.html. Instalei o 10c por ser o último com suporte a português do Brasil. Mas tem até o 10f.
  3. Baixe o driver da LG para o telefone: http://www.mediafire.com/?qvdbresp5nntb6x.
  4. Baixe o KDZ firmware uploader: http://www.unclenet.de/files/KDZ_FW_UPD_EN.7z.
  5. Instale o driver da LG.
  6. Extraia o KDZ_FW_UPD_EN.7z.
  7. Instale o msxml.msi que está dentro do arquivo do KDZ.
  8. Com o telefone desligado e desconectado da porta usb, segure as teclas de aumentar volume, baixar volume e ligar ao mesmo tempo.
  9. O telefone vai iniciar em modo de emergência.
  10. Conecte o telefone no micro pela porta USB.
  11. Passe o controle do dispositivo USB para o VirtualBox: No menu Dispositivos > Dispositivos USB, Marque o telefone LG.
  12. Execute o programa KDZ_FW_UPD.exe, que está dentro do arquivo do KDZ.
  13. Selecione as opções  3GQCT no “Type” e DIAG no “PhoneMode”.
  14. Selecione o arquivo do firmware (V10C_00.KDZ no meu caso).
  15. Inicie a atualização. O post no qual eu me baseei diz que caso haja algum problema, pode-se tentar com o telefone sem a bateria.
  16. No meio da atualização, o telefone é desligado. O controle do dispositivo deve novamente ser passado para o VirtualBox (Dispositivos > Dispositivos USB, como anteriormente). Não sei quanto tempo você tem para fazer isso antes que o KDZ desista, portanto, esteja atento!
  17. Agora ele deve ir até o fim...
A primeira vez que o telefone é ligado, demora bastante para iniciar. Paciência!
Ah, não esqueça de remover a linha no /etc/modprobe.d/blacklist.conf.

Era isso.

domingo, 3 de julho de 2011

The day I've faced a kernel panic in Linux

I've been tempted to switch back from Unity to KDE for several days.
So, today I decided to actually do it.
Everything was fine, then, at some point, after setting up everything, I restarted and...
kernel panic!!!
Wow. For those who haven't seen it, it kind of scares. The numlock and capslock leds on the keyboard keep blinking and nothing else works.
I rebooted again. Same thing. Then again. Sometimes, it was even a hard freeze: not even the blinking leds.
All this happened right after entering the login password in KDM.
Then, I just decided to reinstall everything (I had just installed kubuntu-desktop and uninstalled everything from gnome, as explained here.
After reinstalling, upgrading, configuring... Guess what?
The same thing.
Then I just realized it was when connecting to the wireless network that the system froze.
So, my guess was the wireless card driver. Bingo!!!
I have a Dell Vostro 3300, which comes with a Broadcom  BCM4313 board. The default driver for it is brcm80211.
I had seen several days before in the Hardware Drivers program that another driver was available for it: Broadcom STA driver.
As I had nothing to loose, I just tried, and it worked! \o/
So, here is my tip if anyone encounters a hard freeze or a kernel panic and has the same hardware: install the Broadcom STA driver!
Just as a note, neither KDE nor Kubuntu are to blame here: it was the wireless driver's fault.

terça-feira, 10 de maio de 2011

Não usa Internet Explorer? Você não é mais bem-vindo ao www.smiles.com.br

Sou usuário Linux (o último Windows que usei foi o XP).

Até algum tempo atrás eu acessava sem problemas o site do Smiles (www.smiles.com.br).

Este fim-de-semana tentei acessar e me deparei com um erro, dizendo que eu precisava usar o Microsoft Internet Explorer.

Desiludido, entrei em contato com o "Fale conosco", e, realmente desisti do site.

Me mandaram baixar o Internet Explorer para o meu sistema operacional...

Credo.

Em pleno 2011 ver sites importantes depender de uma plataforma específica é algo que só se explica com ignorância ou mala preta...

Aqui o e-mail na íntegra (salvo os dados pessoais):

Prezado Senhor Luis Fernando:

N° de atendimento: 1-412064905.

Em atenção ao seu e-mail, orientamos verificar e se possível, baixar uma versão do navegador Internet Explorer compatível com seu sistema operacional, pois terá um melhor desempenho durante o acesso ao site Smiles.


Esclarecemos que estamos trabalhando incessantemente para a melhoria de nosso atendimento, com atualizações de sistemas e o Site Smiles.

Pedimos sua compreensão.

Estamos à sua disposição.

Atenciosamente,

Janaina Oliveira
Programa Smiles
VRG Linhas Aéreas S.A - Grupo GOL
www.smiles.com.br/smiles/content/faleconosco/index.htm
Central de Atendimento Smiles: 4003 7001 / 4003 7007
Para localidades não atendidas pelo serviço 4003 ligue para 0800-883-2245.

Favor não responder esta mensagem, caso seja necessário utilize Site “www.smiles.com.br” “My Smiles” “Fale Conosco”, ou utilize o link abaixo. “http://www.smilescom.br/smiles/content/faleconosco/index.htm”.

Texto confidencial para uso exclusivo do destinatário. Não divulgue e apague-o imediatamente se o recebeu por engano.
This is a confidential text to be exclusively used by the recipient. Do not disclose to anybody and delete it immediately if you received it by mistake.
Texto confidencial para uso exclusivo del destinatario. Si usted lo recibi por error no lo divulgue y exclúyalo inmediatamente
Antes de imprimir, pense em sua responsabilidade com o MEIO AMBIENTE.

----- Mensagem Original -----
De: smilesfaleconosco@golnaweb.com.br
Para: smiles.portugues@golnaweb.com.br
Enviada em: 09/05/2011 10:15:59
Assunto: Fale Conosco: Crítica

Fale Conosco - Crítica

Assunto: SITE

Nome: Luis Fernando

Sobrenome: Planella Gonzalez

CPF: XXXXXXX

E-mail: XXXXXXX

Numero Smiles: XXXXXXX

Contato: XXXXXXX

Localizador:

Origem:

Destino:

Data do vôo:

Número do vôo:

Data de ocorrência:

Número Protocolo:

Comentários: É lamentável que não posso mais acessar minha conta no Smiles porque agora o site exige o uso do Microsoft Internet Explorer.
De onde vocês tiraram a ideia infeliz de restringir o acesso a esse navegador, que é sabidamente o mais inseguro de todos?
Sou usuario Linux. Além de me excluir, excluiram os usuarios Mac, iPhone, iPad, Android, Blackbarry ou qualquer coisa que não seja Windows.
Vocês tomaram um passo na contramão da tecnologia, e, apesar de duvidar que isto possa ser solucionado a curto prazo (porque provavelmente investiram milhões no novo sistema mais "seguro"), pelo bem da própria empresa, espero que isto seja mudado algum dia.
As 40.000 milhas que tenho no programa (que ainda não consegui utilizar) serão as últimas investidas no smiles.
Lamentável.

terça-feira, 1 de março de 2011

An example of anti-code

When doing some code review, I've faced this:
var stateOptions = null;
var typeOptions = null;

function hideOptions() {
 if(stateOptions == null) {
  stateOptions = new Array();
  stateOptions[0] = document.getElementById('status').options[0];
  stateOptions[1] = document.getElementById('status').options[1];
  stateOptions[2] = document.getElementById('status').options[2];
  stateOptions[3] = document.getElementById('status').options[3];
  stateOptions[4] = document.getElementById('status').options[4];
  stateOptions[5] = document.getElementById('status').options[5];
 }
 document.getElementById('status').remove(1);
 document.getElementById('status').remove(1);
 document.getElementById('status').remove(1); 
}

function showOptions() {
 document.getElementById('status').remove(0);
 document.getElementById('status').remove(0);
 document.getElementById('status').remove(0);
 try {
  
  document.getElementById('status').add(stateOptions[0], null);
  document.getElementById('status').add(stateOptions[1], null);
  document.getElementById('status').add(stateOptions[2], null);
  document.getElementById('status').add(stateOptions[3], null);
  document.getElementById('status').add(stateOptions[4], null);
  document.getElementById('status').add(stateOptions[5], null);
  
 } catch(ex) {
  document.getElementById('status').add(stateOptions[0], 0);
  document.getElementById('status').add(stateOptions[1], 1);
  document.getElementById('status').add(stateOptions[2], 2);
  document.getElementById('status').add(stateOptions[3], 3);
  document.getElementById('status').add(stateOptions[4], 4);
  document.getElementById('status').add(stateOptions[5], 5);
 } 
}
...

OMG

segunda-feira, 14 de fevereiro de 2011

I must admit: I was poisoned outside KDE...

After having an awful experience with KDE 4.5.0 (described here), I returned to it, as the performance issues were resolved (as I said here).
However, after that experience, something has changed in me...
I was a KDE lover. I found it way better in anything else. But after that...
I've actually been using them both. Kubuntu (with KDE 4.6) at work and Ubuntu at home.
The main point is: KDE's flagship technology is Plasma, which is the desktop, the panel and their widgets (and a few more things). The widgets... All I use is a single panel with a Kickoff menu, a task manager, a pager, a notification area and a clock. Pretty basic, I know. But that's all I need. No desktop widgets. Just a clean desktop and a simple panel.
Kind of, KDE 4, with all it's technologies, is like an overkill.
On the other hand, I never liked GNOME too much. But it gets better with DockbarX and Gnomenu, though ;-)
I must say I'm currently not 100% satisfied by neither KDE nor GNOME.
However, a new kid on the block is getting my attention: Canonical's Unity. The current Maverick netbook interface sucks. It's very slow. But the one shaping up for Natty (to be released in April) is the one I'm looking forward. I've tested the Unity 2D in the current Ubuntu, and it's very fast. And has everything I need: a simple panel and a nice launcher / task manager. Besides, it's beautiful.
Unity has a long way to go, as there's are still 1 alpha and 2 betas before the final launch. I'm really, really anxious to see how Unity will behave as my main desktop in a few months...

domingo, 6 de fevereiro de 2011

Using Querydsl SQL to handle persistence in Java programs

After several years working with Hibernate (since version 1.X - about 2001/2002) and then JPA, I'm quite convinced that for new projects I'd try a new approach: Querydsl SQL. Why? Well, Even though full ORM solutions like Hibernate have several advantages (managing relationships, an easier query language and so on), they also have their drawbacks. I found out that:
  • What I really wanted is an easier way to manipulate databases / resultsets;
  • It always selects all attributes when dealing with entities. I know you CAN select individual attributes, but this is more an exception than a rule. People tend to just read the entire record, and then accessing the needed attributes. Some argue that this is not something which impacts performance, but after some fine tuning on my current project, I realized that every gain matters;
  • Pure OO in data manipulation is nice, but the impedance mismatch just can't be negleted. It will bite you sooner or later;
  • You always end up with a few cases where native query is needed, or the performance is just not acceptable. I think that programs are coded by developers, but those who really needed to be pleased are the end users. And poor performance just produces bad mood on users;
  • Even though JPA 2 has most of the features Hibernate has, it brings a problem: Just like most (all?) JCP specifications, it always has points left out of the specification. So, having a (relatively complex) system working with a JPA provider (say, Hibernate) and migrating it to another one (EclipseLink, OpenJPA, ...) is not failproof. This just leads to frustration...

Ok, I know no framework / library / technology is perfect, but I think Querydsl SQL is quite promising. Here are a few points:
  • You have full power of native queries, with type-safe queries. Java classes are generated based on the database tables, so you have the full power of IDE's (autocomplete, finding references, code analysis...). This is a boost on productivity;
  • Queries can return several types of data, like iterators, lists, maps or single objects. The projection type can be beans, arrays, tuples or custom expressions. Querydsl is very easy to extended;
  • It can also handle data manipulation (inserts, updates and deletes). This kind of removes all cases one would need to touch the connection;
  • Besides to generating the Q-types (Java classes representing the database tables), it is also possible to generate beans (DTOs) for the tables. This is nice for cases where you want all columns of the table, but optional. Using them can boost the productivity, as avoids having to create each bean by hand.

So, enough talking! Let's take a look on some code. The example here is of a simple blog: We have users, which can create posts and commenting existing posts. So, here is the DDL for MySQL:
drop table if exists comment;
drop table if exists post;
drop table if exists user;

create table user (
    id bigint not null,
    name varchar(100) not null,
    username varchar(20) not null,
    password varchar(20) not null,
    primary key (id)
) engine innodb;

create table post (
    id bigint not null,
    user_id bigint not null,
    title varchar(250) not null,
    date datetime not null,
    contents text not null,
    primary key (id),
    constraint fk_post_user foreign key (user_id) references user(id)
) engine innodb;

create table comment (
    id bigint not null,
    user_id bigint not null,
    post_id bigint not null,
    date datetime not null,
    comments text not null,
    primary key (id),
    constraint fk_comment_user foreign key (user_id) references user(id),
    constraint fk_comment_post foreign key (post_id) references post(id)
) engine innodb;

So, we need to invoke Querydsl to read the database tables and generate the Java classes. Beans will be generated as well:
Configuration configuration = new Configuration(new MySQLTemplates());
NamingStrategy namingStrategy = new DefaultNamingStrategy();
MetaDataExporter exporter = new MetaDataExporter();
exporter.setConfiguration(configuration);
exporter.setNamePrefix("Q");
exporter.setTargetFolder(new File("generated"));
exporter.setSerializer(new MetaDataSerializer("Q", namingStrategy));
exporter.setBeanSerializer(new BeanSerializer());
exporter.setNamingStrategy(namingStrategy);
exporter.setPackageName("demo.blog");
        
Connection connection = ... //Get connection
exporter.export(connection.getMetaData());

If you are in Eclipse, just refresh the project and add the generated folder as source folder. There you will find the QUser, QPost and QComment classes, as well as the beans: User, Post and Comment.

Before showing some data manipulation code, here are some methods used by the examples (the configuration can be created the same way as in the example above):
SQLDeleteClause delete(RelationalPath path) {
    return new SQLDeleteClause(
        getConnection(), getConfiguration(), path);
}

SQLQuery from(Expression from) {
    SQLQueryImpl query = new SQLQueryImpl(
        getConnection(), getConfiguration());
    query.from(from);
    return query;
}

SQLInsertClause insert(RelationalPath path) {
    return new SQLInsertClause(
        getConnection(), getConfiguration(), path);
}

SQLUpdateClause update(RelationalPath path) {
    return new SQLUpdateClause(
        getConnection(), getConfiguration(), path);
}

So, here are some examples for manipulating data:
QUser user = QUser.user; //Generated Q-type

// Create an user
User john = new User();
john.setName("John Smith");
john.setUsername("jsmith");
john.setPassword("john_secret");
Long johnId = insert(user)
    .populate(john)
    .executeWithKey(user.id);
john.setId(johnId);

// Create a post
QPost post = QPost.post;
Post newPost = new Post();
newPost.setDate(new Date());
newPost.setUserId(john.getId());
newPost.setTitle("A very interesting Java post!");
newPost.setContents("For more posts, visit http://freeit.inf.br");
Long postId = insert(post)
    .popupate(newPost)
    .executeWithKey(post.id);
newPost.setId(postId);

// Without using generated beans
Long maryId = 10L;
QComment comment = QComment.comment;
insert(comment)
    .set(comment.date, new Date())
    .set(comment.postId, post.getId())
    .set(comment.userId, maryId)
    .set(comment.comments, "Love your post... Keep on!")
    .execute();

// Then, john decides to edit the post title
update(post)
    .set(post.title, "Using Querydsl...")
    .set(post.contents, post.contents.concat("\\n\\n[updated]"))
    .where(post.id.eq(post.getId()))
    .execute();

// And Mary removes all her comments on all posts!
delete(comment)
    .where(comment.userId.eq(maryId)
    .execute();

Enough DML examples. Let's perform some queries (using the same user, post and comment variables from above):
//Listing comments using the generated bean
List<Comment> postComments = 
    from(comment)
    .where(comment.postId.eq(postId))
    .list(comment);

//Iterating through all users with comments
CloseableIterator<User> usersWithComments = 
    from(user)
    .rightJoin(comment.commentUserFk, user)
    .where(comment.id.isNotNull())
    .iterateDistinct(user);

On the last example, it's possible to see that even the foreign keys are imported into the model, and can be used on joins. You can also use subqueries, factory expressions to invoke custom SQL functions and so on. Visit www.querydsl.com for documentation and downloads.

So, here is my tip. If you are looking for an alternative in data access in Java, give Querydsl SQL a try.

sábado, 8 de janeiro de 2011

My [terrible] experiences with EJB

In the past (around 2004), I had worked with EJB 2. I hated it. Too much xml, too much complexity. Home / remote / local interfaces... So, at the time, as a workaround, I built a framework which implemented the command pattern, having a single EJB deployed, and passing the command and parameters for it. Not good.
Then, in my current project, we started with EJB 3 (in late-2008). Mostly because it's standard. It is surely much easier, with annotations and such. However, the project has security requirements way beyond the standard JAAS can handle. Besides roles (the only concept handled by JAAS in EJBs), we have permission sets, which can be applied to either groups or individual users, and they can be dynamically changed by the application admins. So we had to create some sort of custom mechanism to check permissions. However, we still need JAAS to propagate the user identity (we use remote EJB interfaces).
Ok, but why am I so disappointed with EJBs? Here are some points:

  • To propagate the caller identity we need JAAS. It is insufficient to the application I'm working on (and would be too for some others which I had already worked, so, either I'm too unlucky or the standard is weak).
  • Again on JAAS: For the application side, it's standard. However, for every application server out there, there is a distinct way to configure it. Ok, for applications which find users and plain or hashed passwords in a DB table, probably there is an easy way to configure some sort of login module with an SQL query. However, in our application, the credentials are dynamic as well, depends on the application configuration and on the application channel being accessed, and, as logic to validate all those is on the application, I'd like to use the application itself to validate users. However, in some containers, it's quite complicated to invoke the application to validate users. Go figure... 
  • Once again on JAAS: Because the JAAS configuration is specific for each application server, it's virtually impossible to just deploy an application in more than one application server without headache. So, if you code your application in an standard way, and cannot reliably deploy that same application on distinct standard-compliant application servers, then that standard is void and defective by design. In the other hand, a self-contained web application can be deployed on ANY web container (as long as you don't use that little friend, JAAS).
  • Application servers take a lot of time to startup and deploy the application. Even though they are faster than some years ago, they are still slow. Compare the startup time with a simple web application running on a Tomcat or Jetty - just (very) few seconds.
  • JPA has it's share of guilty in the slow startup times. For the current project, Hibernate alone takes about 30-40 seconds to map every entity (about 200 tables).
  • The runtime performance for EJBs is also likely to be slower than a regular web applications. You can cluster, I know. But there are way too much proxies, interceptors, lookups, injections... I can't prove with numbers. But common sense tells me that.
  • The standard API for type-safe queries in JPA (criteria API) is an abomination. But I had already discussed that, and solved it by using Querydsl.

Conclusions? For future projects I'll try to avoid EJBs as much as possible. Spring is likely to always be in the game for me, as it's a fantastic piece of software. Also, after so many years working with Hibernate (since 1.2.x) and later JPA, I'm pretty sure I would likely choose Querydsl SQL mode, which has no ORM, but has type-safe queries and DMLs (insers / updates / deletes). Also, it's metamodel is generated at compilation time, it has almost zero overhead on the application initialization (Hibernate as already stated, for us, takes 30-40 seconds just to initialize the persistence).
That is the beauty (but also for me, as a software architect, a frustration) of Java development. You have thousands of frameworks and libraries to choose from, and when most non-trivial projects are finished and set to production, they already use legacy technologies.