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

domingo, 30 de janeiro de 2011

java metadata

Olá, encontrei um código interessante e resolvi postar aqui.. ele verifica se algum atributo de um determinado objeto possui a annotation Id..

Quando eu tiver mais tempo vou dar uma pesquisada maior sobre isso... essa questão de metadata é bem interessante, procurando no google existe bastante material sobre isso.

http://pastie.org/1505699

/**
* Verifica se a entidade em questão possui um Id. Método utilizado para escolher
* se a o esquema de persistência deve salvar ou atualizar o modelo
* @param entity A entidade a ser verificada
* @return true se a entidade possui Id
* @throws Exception Caso algo de errado, uma exceção será lançada
*/
public boolean hasId(Object entity) throws Exception{
Class clazz = entity.getClass();
for(Field f : clazz.getDeclaredFields()){
if(!f.isAccessible())
f.setAccessible(true);
if(f.isAnnotationPresent(Id.class)){
if(f.get(entity) != null){
log.info("ID found: "+f.get(entity));
return true;
}
}
}
return false;
}

Alguns links interessantes:
http://www.guj.com.br/articles/136
http://java.sun.com/products/jmi/
http://download.oracle.com/javase/1.4.2/docs/api/java/sql/DatabaseMetaData.html
http://download.oracle.com/javase/1.5.0/docs/api/java/lang/reflect/AnnotatedElement.html
http://download.oracle.com/javase/6/docs/api/java/lang/reflect/AccessibleObject.html

Vaaleu!
Adriano Schmidt

terça-feira, 25 de janeiro de 2011

SQL - ignorar horas

Oi,

Fiz a segunte query:

select m from MinhaTabela m where :date between m.initialDate AND m.endDate

e tive o seguinte problema: o meu parâmetro :date era uma data com as horas 00:00, porém o initialDate era sempre com horário (12:30 por exemplo), então minha query nunca retornava nada.

Para igorar as horas utilizei a função date()

select m from MinhaTabela m where :date between date(m.initialDate) AND date(m.endDate)

Pronto! Dessa forma o horário foi ignorado e a comparação foi feita utilizando somente as datas e tudo funcionou : )

Mais funções de data e hora podem ser encontradas em: http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html

Vaaleu!
Adriano Schmidt

segunda-feira, 24 de janeiro de 2011

richfaces popupPanel ie8

Olá,

Estou num projeto utilizando JSF 2.0 e RichFaces 4.

Meu popupPanel (antigo modalPanel) estava desrespeitando os atributos width e height no ie8 ficando bem grande no browser.. no firefox tudo funcionava perfeitamente.

O problema era que eu estava usando o componente inputCalendar do tomahawk.. ao usar a propriedade renderAsPopup como true, o meu popupPanel se perdia e ficava com um tamanho diferente do que setei.

Solução: Troquei o inputCalendar do tomahawk pelo calendar do RichFaces.

Show! Funcionou!
Adriano Schmidt

quarta-feira, 22 de dezembro de 2010

@EJB não funciona

A injeção via @EJB só funciona em classes gerenciadas pelo container EJB, em outros casos é preciso fazer lookup:

Tive esse problema pois no projeto que estou agora fiz uma camada de delegates. A parte de telas do meu projeto não acessa diretamente meus serviços.. acessa um delegate que esse sim acessa meus serviços.

Como meu delegate não é uma classe gerenciada pelo container EJB tive que fazer lookup:

/////////////////
public class AaaDelegate {

private AaaService aaaService;

public AaaDelegate() {
this.aaaService = (AaaService) this.lookup(AaaService.JNDI);
}

public Object lookup(String jndi) {

try {
Context context = new InitialContext();
return context.lookup(jndi);
} catch (NamingException e) {
e.printStackTrace();
}

return null;
}

///////////////

@Local
public interface AaaService {

public static String JNDI = "aaa.AaaService";

}

/////////////

@Stateless
@LocalBinding(jndiBinding = AaaService.JNDI)
public class AaaServiceImpl implements AaaService {

}

////////////


Vaaleu!

Referência Cíclica EJB

Oi, hoje tive um problema de referência cíclica (cycle services dependiency ou circular references ou ainda cyclic reference) com EJBs..

Na classe AaaServiceBean eu tinha isso:

@EJB
private BbbService bbbService;

E na classe BbbServiceBean eu tinha:

@EJB
AaaService aaaService;

Isso causava um erro de referência cíclica, pois Aaa tinha um Bbb e Bbb tinha um Aaa. Para resolver isso adicionei a annotation org.jboss.ejb3.annotation.IgnoreDependency em uma das classes:

A classe AaaServiceBean ficou assim:

@EJB
@IgnoreDependency
private BbbService bbbService;


Pronto! Problema resolvido. O que esse IgnoreDependency faz exatamente eu não sei, não encontrei nenhuma documentação interessante, mas, funcionou.

Vaaleu, abraço!

UIInstructions cannot be cast to AbstractTogglePanelItem

Hoje me aconteceu o seguinte erro num projeto com jsf2 e richfaces4:

com.sun.faces.facelets.compiler.UIInstructions cannot be cast to org.richfaces.component.AbstractTogglePanelItem

No meu caso descobri que o que causava isso eram comentários dentro do tabPanel.

NÃO FUNCIONA:
<rich:tabPanel>
<rich:tab header="aaaaa">
<h:outputText value="aaaaaaaaaa"></h:outputText>
</rich:tab>
<!— esse comentario gerou o erro -->
<rich:tab header="bbbbb">
<h:outputText value="bbbbbbbbbb"></h:outputText>
</rich:tab>
</rich:tabPanel>

FUNCIONA:
<rich:tabPanel>
<rich:tab header="aaaaa">
<h:outputText value="aaaaaaaaaa"></h:outputText>
</rich:tab>
<rich:tab header="bbbbb">
<h:outputText value="bbbbbbbbbb"></h:outputText>
</rich:tab>
</rich:tabPanel>


Log com mais detalhes:
10:36:35,449 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] Error Rendering View[/resources/user/UserForm.xhtml]: java.lang.ClassCastException: com.sun.faces.facelets.compiler.UIInstructions cannot be cast to org.richfaces.component.AbstractTogglePanelItem
at org.richfaces.renderkit.html.TogglePanelRenderer.getChildrenScriptObjects(TogglePanelRenderer.java:178) [:4.0.0-SNAPSHOT]

[…]
10:36:35,493 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/l8-web].[Faces Servlet]] Servlet.service() for servlet Faces Servlet threw exception: java.lang.ClassCastException: com.sun.faces.facelets.compiler.UIInstructions cannot be cast to org.richfaces.component.AbstractTogglePanelItem
at org.richfaces.renderkit.html.TogglePanelRenderer.getChildrenScriptObjects(TogglePanelRenderer.java:178) [:4.0.0-SNAPSHOT]
at org.richfaces.renderkit.html.TogglePanelRenderer.getScriptObjectOptions(TogglePanelRenderer.java:147) [:4.0.0-SNAPSHOT]

[…]

Exportar dados mysql

Olá,

No terminal de comando basta executar a seguinte linha de comando:

mysqldump -u root -p -r c:\dados.sql nomeDoBanco

altere nomeDoBanco pelo nome do banco
altere root pelo nome do usuário
altere c:\dados.sql pelo diretório/arquivo.sql onde os dados serão gravados

Depois será solicitada a senha e então os dados serão exportados para o arquivo indicado.

Vaaleu!