terça-feira, 8 de fevereiro de 2011

SQL Server - Apparently wrong driver class specified for URL

Olá, hoje tive o seguinte erro ao iniciar o JBoss num ambiente SQL Server 2000:

15:45:18,348 WARN [JBossManagedConnectionPool] Throwable while attempting to get a new connection: null: org.jboss.resource.JBossResourceException: Could not create connection; - nested throwable: (org.jboss.resource.JBossResourceException: Apparently wrong driver class specified for URL: class: com.microsoft.sqlserver.jdbc.SQLServerDriver, url: jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydatabase)

O problema era a URL de conexão com o banco no meu arquivo ds.xml, tirei o :microsoft

jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydatabase
jdbc:sqlserver://localhost:1433;DatabaseName=mydatabase

Vaaleu!
Adriano Schmidt

segunda-feira, 7 de fevereiro de 2011

JSF Acentuação IE

Olá, eu estava tendo problemas com caracteres especiais.. nos meus cadastros as palavras que tinham acento ou cedilha chegavam no java desconfiguradas (São Paulo virava São Paulo).

Fiz algumas tentativas frustradas:

<f:view contentType="text/html; charset=UTF-8" encoding="UTF-8">
<f:view contentType="text/html; charset=ISO-8859-1" encoding="ISO-8859-1">
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
<meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1' />
<h:form acceptcharset="UTF-8">
<h:form acceptcharset="ISO-8859-1"> (essa funcionou em todos os browsers, menos no ie)

Alterei o web.xml:
<locale-encoding-mapping-list>
<locale-encoding-mapping>
<locale>pt< <encoding>ISO-8859-1</encoding> (tentei com UTF-8 tmb)
</locale-encoding-mapping>
</locale-encoding-mapping-list>

Mas nada funcionou...

Pra resolver fiz o seguinte:

Coloquei a seguinte linha no início de todos os .xhtml
<?xml version="1.0" encoding="UTF-8"?>

No web.xml eu adicionei o seguinte:
<filter>
<filter-name>CharsetFilter</filter-name>
<filter-class>br.com.localhost8080.infrastructure.CharsetFilter</filter-class>
<init-param>
<param-name>requestEncoding</param-name>
<param-value>ISO-8859-1</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>CharsetFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

E criei uma classe chamada CharsetFilter no pacote br.com.localhost8080.infrastructure:

package br.com.localhost8080.infrastructure;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class CharsetFilter implements Filter {

private String encoding;

public void init(FilterConfig config) throws ServletException {
this.encoding = config.getInitParameter("requestEncoding");

if (this.encoding == null) {
this.encoding = "ISO-8859-1";
}
}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain next) throws IOException, ServletException {
if (null == request.getCharacterEncoding()) {
request.setCharacterEncoding(this.encoding);
}

response.setContentType("text/html; charset=ISO-8859-1");
response.setCharacterEncoding("ISO-8859-1");

next.doFilter(request, response);
}

public void destroy() {
}
}

Isso resolveu o problema de acentuação no submit dos formulários em todos os browsers (Para essa resolução foi de grande ajuda o site stackoverflow.com)

Porém... eu ainda tava com problemas no internet explorer em alguns campos que eram atualizados via ajax ou via rerenderização da tela no retorno de forms.

Para resolver isso criei dois converters, um eu uso para campos atualizados via ajax (ConverterCharset) e outro eu uso para campos atualizados via rerenderização da tela nos retornos dos forms (ConverterString).

Para campos atualizados via ajax é necessário adicionar converter="converterCharset"
<h:inputText value="#{myBean.myObject.name}" converter="converterCharset"/>

ConverterCharset.java:
package br.com.localhost8080.infrastructure;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;

import br.com.localhost8080.infrastructure.StringUtils;

@FacesConverter(value = "converterCharset")
public class ConverterCharset implements Converter {

public Object getAsObject(FacesContext arg0, UIComponent arg1, String value) throws ConverterException {
return value;
}

public String getAsString(FacesContext arg0, UIComponent arg1, Object value) throws ConverterException {
String convertedString = StringUtils.convertUtf8ToIso88591(value);
return convertedString;
}
}

ConverterString.java:

package br.com.localhost8080.infrastructure;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;

import br.com.localhost8080.infrastructure.StringUtils;

@FacesConverter(forClass = String.class, value="Test")
public class ConverterString implements Converter {

//vem da tela / request
public Object getAsObject(FacesContext arg0, UIComponent arg1, String value) throws ConverterException {
if ("".equals(value.toString().trim())) {
return null;
}

String convertedString = StringUtils.convertUtf8ToIso88591(value);
return convertedString;
}

//vai para tela / response
public String getAsString(FacesContext arg0, UIComponent arg1, Object value) throws ConverterException {
String convertedString = StringUtils.convertUtf8ToIso88591(value);
return convertedString;
}
}

Ambos os converters tinham um código de conversão de UTF-8 para ISO-8859-1 que foi externalizado para a classe StringUtils.
package br.com.localhost8080.infrastructure;

public class StringUtils {
/**
* Verifica se valor string do objeto passado como parametro e UTF-8 e entao converte para ISO-8859-1
*/
public static String convertUtf8ToIso88591(Object value) {
if (value instanceof String == false) {
return value.toString();
}

String originalValue = (String) value;

// verifica se e UTF-8 (se tem caracteres especiais)
if (originalValue.contains("Ã") || originalValue.contains("Â")) {
java.nio.charset.Charset utf8charset = java.nio.charset.Charset.forName("UTF-8");
java.nio.charset.Charset iso88591charset = java.nio.charset.Charset.forName("ISO-8859-1");
java.nio.ByteBuffer inputBuffer = java.nio.ByteBuffer.wrap(originalValue.getBytes());
// decode UTF-8
java.nio.CharBuffer data = utf8charset.decode(inputBuffer);
// encode ISO-8559-1
java.nio.ByteBuffer outputBuffer = iso88591charset.encode(data);
byte[] outputData = outputBuffer.array();

String convertedString = new String(outputData);

// se a conversao deu errado retorna o valor original
if (convertedString.contains("?")) {
return originalValue;
}

// retorna o valor convertido
return convertedString;
}

return originalValue;
}
}


É isso.. sem mais problemas de acentuação.

Abraço,
Adriano Schmidt

sexta-feira, 4 de fevereiro de 2011

persistence.xml dinâmico

E aew!

Bom, eu defino o hibernate.dialect no persistence.xml, porém o meu persistence.xml estava dentro do meu ear.. dessa forma quando fosse necessário trocar o dialeto, era necessário alterar o ear. Eu não queria isso. Então para externalizar o hibernate.dialect tentei o seguinte:

Tirei a linha do hibernate.dialect do persistence.xml e iniciei o JBoss passando o parâmetro -Dhibernate.dialect=org.hibernate.dialect.MySQLDialect

Aconteceu o seguinte erro:

17:55:16,514 ERROR [JDBCExceptionReporter] Unexpected token: LAST_INSERT_ID in statement [select last_insert_id()]
state=Create: java.lang.RuntimeException: javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not retrieve generated id after insert:
[org.jboss.ejb3.timerservice.mk2.persistence.TimeoutMethod]

Bom, pra resolver isso iniciei o JBoss com um parâmetro diferente:
-Dlocalhost8080.hibernate.dialect=org.hibernate.dialect.MySQLDialect

E essa propriedade eu usei no persistence.xml:
<property name="hibernate.dialect" value="${localhost8080.hibernate.dialect}"/>

Obs: Você pode trocar o localhost8080 do localhost8080.hibernate.dialect para o nome do seu projeto.

Pronto, dessa forma tudo funcionou!!!!


Também seria possível configurar o hibernate.dialect via código, mas não era esse meu objetivo.

Se você quiser colocar essa propriedade (localhost8080.hibernate.dialect) num arquivo de propriedades para que não seja necessário setá-la na inicialização do JBoss, faça o seguinte:

No arquivo properties-service.xml que fica em <jboss>\server\<context>\deploy dentro do mbean SystemProperties deve adicionar a propriedade, ficando dessa forma:

<mbean code="org.jboss.varia.property.SystemPropertiesService"
name="jboss:type=Service,name=SystemProperties">

<attribute name="Properties">
localhost8080.hibernate.dialect=org.hibernate.dialect.MySQLDialect
</attribute>

</mbean>

Vaaaleu!
Adriano Schmidt