Mostrando postagens com marcador java. Mostrar todas as postagens
Mostrando postagens com marcador java. Mostrar todas as postagens

terça-feira, 13 de setembro de 2016

Load balancer com WildFly 10

Esse passo a passo mostra como montar um ambiente com um Apache HTTP Server como loadbalancer e vários WildFly 10 atrás utilizando sempre o modo standalone.

Bom, trabalho com JBoss/WIldFly desde a versão 3 e já montei ambientes load balancer e cluster em mais de 20 ambientes... Esse mês montei novamente utilizando o WildFly 10 para um cliente que estou dando consultoria.

Antes de mais nada agradeço a todos do JBug Brasil. Sem a galera desse grupo eu não saberia nem iniciar o WildFly :) Entrem lá, recomendo!

O ambiente será assim:




Standalone ou domain?
Resolvi usar o modo standalone pois acredito que o modo domain adiciona um pouco mais de complexidade que não é necessária para ambientes com poucos servidores WildFly....

o domain serve apenas para centralizar as configurações em uma máquina só... caso queira fazer usando o modo domain, basta seguir esse tutorial e depois alterar para o modo domain....


Load balancer e/ou cluster

Aqui mostro apenas o como fazer um Load Balancer... não mostro como fazer um cluster... mas em muitos (talvez na maioria) dos ambientes, o cluster não é necessário....

O Load balancer serve para permitir escalabilidade... então atrás do Apache vai ter vários WildFly e você pode adicionar mais caso necessário (caso aumente o número de usuários por exemplo)

O Load balancer serve para redundância... se cair um WildFly, outro WildFly vai assumir....

"Tá Adriano, então pra que serve o cluster?"

O cluster serve para permitir o compartilhamento de dados de sessão.. por exemplo... no load balancer se vc estiver logado e de repente o WildFly cair, outro WildFly vai assumir, mas você voltará para a tela de login e terá q fazer login de novo... pois dados de sessão não são compartilhados no load balancer....

Para permitir que o usuário continue logado, você teria que ter um cluster...

Como os WildFly não vão cair o tempo inteiro... e se quando cair não for um problema tão grande o usuário ter q fazer login de novo... você não precisa de cluster....

Se você quiser fazer um cluster tudo bem.... não é muuuito dificil, é só seguir esse tutorial e depois alterar mais algumas coisinhas para implementar o cluster, mas não vou mostrar isso neste post...

Ahhh... E caso você esteja usando Amazon ou Digital Ocean... fazer um cluster vai ser um pouco mais difícil pois eles não permitem multicast (q é como as máquinas do cluster se comunicam) e você teria que fazer isso de outra forma... o q não é tããão simples...

Post passo-a-passo

Talvez (ou não) vc esteja se perguntando:
"Este passo-a-passo é completo e é só seguir que vai dar certo?"

Não! Esse passo-a-passo provavelmente não vai estar 100% claro e talvez falte algum detalhe... Foram anotações que fiz quando estava montando esse ambiente...

Não achei nenhum passo-a-passo mostrando como montar um load balancer com WildFly 10... por isso resolvi postar aqui mesmo que falte algum detalhe...

Até pq quando você for usar talvez vc use alguma versão diferente do que usei ou talvez seja diferente na sua infra ou no seu S.O.

Já montei load balancers e clusters em mais de 20 ambientes... e todas as vezes deu algum problema diferente...

"Tá Adriano, mas se não tá completo então esse post é inútil"

Acredito que é útil sim! talvez vc vai ter alguma dificuldade em algum ponto... aí vc abre um chamado no JBug Brasil e eu e outros caras que são bem legais vamos tentar te ajudar.


Vamos lá!


Você precisará de 3 máquinas:
- maq01: Apache HTTP Server
- maq02: WildFly Server1
- maq03: WildFly Server2

Sistema operacional
Sugiro o uso do sistema operacional RHEL (Red Hat Entrerprise Linux) ou CentOS (que é igual ao RHEL só que da comunidade).
Mas já implantei isso no Ubuntu também.
No Windows deve dar também... mas esse post vai ser todo focado em linux...


Em todas as máquinas faça esses passos:

- Configure a rede conforme desejado:
/etc/init.d/network stop
vi /etc/sysconfig/network-scripts/ifcfg-eth0
vi /etc/sysconfig/network
vi /etc/resolv.conf
/etc/init.d/network start

- Teste se a rede está OK
ping www.google.com
ifconfig


Maq01 - Apache HTTP Server

Documentação complementar:
https://docs.jboss.org/mod_cluster/1.1.0/html/native.config.html
https://httpd.apache.org/docs/2.4/howto/access.html

Apache 2.2
Aqui vou falar como implantar com o Apache 2.2... mais pra baixo comento como é com o Apache 2.4

yum install httpd httpd-devel apr-devel openssl-devel mod_ssl -y

sudo service httpd start


- Acesse no browser de sua máquina e verifique se o Apache HTTP Server está no ar, só acessar pelo ip: http://<ip da maquina>

- Baixe o mod_cluster (sempre utilize a versão mais atual ao invés de usar o comando abaixo, procure em http://mod-cluster.jboss.org/)
wget http://downloads.jboss.org/mod_cluster//1.3.1.Final/linux-x86_64/mod_cluster-1.3.1.Final-linux2-x64-so.tar.gz
tar -zxvf mod_cluster-1.3.1.Final-linux2-x64-so.tar.gz
cp mod_advertise.so /etc/httpd/modules/
cp mod_manager.so /etc/httpd/modules/
cp mod_proxy_cluster.so /etc/httpd/modules/
cp mod_cluster_slotmem.so /etc/httpd/modules/

- Comente a linha do mod_proxy_balancer pois será usado o mod_cluster
cd /etc/httpd/conf.modules.d
vi 00-proxy.conf

- A linha deve ficar assim:
#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so


- Crie e adicione o conteúdo do arquivo mod_cluster.conf
cd /etc/httpd/conf.d/
touch mod_cluster.conf
vi mod_cluster.conf

LoadModule cluster_slotmem_module modules/mod_cluster_slotmem.so
LoadModule manager_module modules/mod_manager.so
LoadModule proxy_cluster_module modules/mod_proxy_cluster.so
LoadModule advertise_module modules/mod_advertise.so

MemManagerFile /var/cache/mod_cluster

Maxcontext 100
Maxnode 100
Maxhost 100

<VirtualHost *:80>

<Directory />
Order deny,allow
Allow from all
</Directory>

<Location /mod_cluster_manager>
SetHandler mod_cluster-manager
#Order deny,allow
#Deny from all
#Allow from all
AuthType Basic
AuthName "MCM"
AuthUserFile /etc/modclusterpassword
Require user admin
</Location>

KeepAliveTimeout 60
MaxKeepAliveRequests 0
ServerAdvertise Off
EnableMCPMReceive Off

</VirtualHost>



Apache 2.4
Essa semana instalei esse ambiente no Ubuntu e no Apache 2.4... teve algumas diferenças...

Para fazer isso (Apache 2.4 no Ubuntu) usei esse passo-a-passo:
https://symbiotics.co.za/configure-apache-with-mod_cluster-load-balancer-on-ubuntu/


Se acontecer o erro:

apache2: Syntax error on line 140 of /etc/apache2/apache2.conf:
Syntax error on line 3 of /etc/apache2/mods-enabled/proxy_cluster.load:
Cannot load /usr/lib/apache2/modules/mod_proxy_cluster.so into server:
/usr/lib/apache2/modules/mod_proxy_cluster.so: undefined symbol: ap_proxy_hashfunc



A solução é deixar o arquivo "proxy_cluster.load" dessa forma:

LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
LoadModule cluster_slotmem_module /usr/lib/apache2/modules/mod_cluster_slotmem.so
LoadModule manager_module /usr/lib/apache2/modules/mod_manager.so
LoadModule advertise_module /usr/lib/apache2/modules/mod_advertise.so
LoadModule proxy_cluster_module /usr/lib/apache2/modules/mod_proxy_cluster.so


Além disso, aconteceu o erro:

[Thu Aug 25 18:01:33.049309 2016] [proxy:warn] [pid 5911:tid [...] [client 177.101.142.200:58291] AH01144: No protocol handler was valid for the URL /systemprops. If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule.

Ali onde estou carregando os módulos então tive que adicionar a seguinte linha:

LoadModule proxy_ajp_module /usr/lib/apache2/modules/mod_proxy_ajp.so

Mais detalhes em: https://developer.jboss.org/thread/272092. Agradeço ao Ingo e filippe.spolti do JBug Brasil pela ajuda nesse problema.


Além disso, deu o erro:

2016-08-23 19:38:20,417 ERROR [org.jboss.modcluster] (UndertowEventHandlerAdapter - 1) MODCLUSTER000042: Error null sending INFO command to ip-<IP INTERNO DO APACHE>.sa-east-1.compute.internal/<IP INTERNO DO APACHE>:80, configuration will be reset: null


A solução... meu conf do apache estava assim:

<Directory />
     Order deny,allow
     Allow from all
</Directory>

Mas na versão Apache 2.4 tem que ser assim:

<Directory />
    AllowOverride none
    Require all granted
</Directory>

Mais detalhes em: https://developer.jboss.org/thread/272023



- Crie um usuário e senha
htpasswd -c /etc/modclusterpassword admin

- Reinicie o Apache:
sudo service httpd stop
sudo service httpd start

- Teste novamente no browser: http://<ip_da_maquina>

- Teste no browser o mod_cluster: http://<ip_da_maquina>/mod_cluster_manager




Maq02, Maq03

- Instale e configure o Java (Sempre use a versão mais atual)

Aqui está um exemplo de como instalar (no caso Java 7, mas use o 8), mas pode fazer como achar melhor.
wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.rpm

rpm -Uvh jdk-7u79-linux-x64.rpm

alternatives --install /usr/bin/java java /usr/java/latest/jre/bin/java 200000
alternatives --install /usr/bin/javaws javaws /usr/java/latest/jre/bin/javaws 200000
alternatives --install /usr/bin/javac javac /usr/java/latest/bin/javac 200000
alternatives --install /usr/bin/jar jar /usr/java/latest/bin/jar 200000


- Instale o WildFly (Sempre baixe a versão mais atual):
Aqui está o 8, mas use o 10 ou superior:

wget http://download.jboss.org/wildfly/8.2.0.Final/wildfly-8.2.0.Final.zip

yum install unzip

unzip wildfly-8.2.0.Final.zip  -d /opt/
ln -s /opt/wildfly-8.2.0.Final /opt/wildfly


- Configure um usuário no linux:
groupadd wildfly
useradd -s /bin/bash -d /home/wildfly -m -g wildfly wildfly
chown -R wildfly:wildfly /opt/wildfly-8.2.0.Final
chown -h wildfly:wildfly /opt/wildfly

sudo vi /etc/sudoers
wildfly ALL=(ALL) NOPASSWD:ALL

passwd wildfly
su wildfly


- Inicie o WildFly rodando o standalone.sh da pasta bin passando como parâmetro o profile full-ha
./standalone.sh -server-config=standalone-full-ha.xml

- Veja no log se não deu erros
vi /opt/wildfly/standalone/log/server.log

- Pare o WildFly


- Adicione as linhas de JAVA_OPTS:
vi /opt/wildfly/bin/standalone.conf
JAVA_OPTS="$JAVA_OPTS -Djboss.bind.address=<IP MAQUINA>"

Ao invés de IP da máquina você pode usar 0.0.0.0 que é mais genérico



- Configure o mod_cluster no WildFly:
- acesse o arquivo standalone-full-ha.xml
- procure o subsystem modcluster e altere o conteúdo dele para:

<mod-cluster-config advertise-socket="modcluster" proxies="apache1" advertise="false" sticky-session="true" load-balancing-group="arquitetura" connector="ajp">
   <dynamic-load-provider>
     <load-metric type="cpu"/>
   </dynamic-load-provider>
</mod-cluster-config>


-dentro do seu socket-binding-group, você deve colocar isso:

<outbound-socket-binding name="apache1">
<remote-destination host="<IP INTERNO DO APACHE>" port="80"/>
</outbound-socket-binding>

Mais sobre isso: https://developer.jboss.org/thread/272022


- Inicie o WildFly
./standalone.sh -server-config=standalone-full-ha.xml


- Faça deploy de uma aplicação de testes
- Faça o deploy da aplicação systemprops jogando o war na pasta deployments do WildFly: https://dl.dropboxusercontent.com/u/8155843/TDC%20Floripa%202015/systemprops.war

Teste o load balancer
1) Acesse via broser a aplicação pelo apache http server: http://<ip_do_apache>/systemprops
2) A aplicação mostrará em qual host você vai estar: arquitetura-1 ou arquitetura-2. Vai depender de onde o loadbalancer te direcionou
3) Vá até a máquina que você foi direcionado (arquitetura-1 por exemplo) e pare o WildFly
4) Acesse a mesma URL e veja que você foi redirecionado para o arquitetura-2, ou seja, o loadbalancer está funcinando
5) Suba novamente o wildfly


Segurança
- Nunca inicie nada como root
- Não deixe acessível na web o servidor onde está o WildFly (configuração de infra). Resumindo, você não pode conseguir pingar o servidor onde está o WildFly, pois só o servidor do Apache deve estar disponível.
- Use SSL
- Permita o acesso ao mod cluster manager apenas na rede interna (melhor opção) ou apenas para um determinado IP. Algo como:
<Location /mod_cluster_manager>
SetHandler mod_cluster-manager
Order deny,allow
Deny from all
Allow from <seu_ip>
AuthType Basic
AuthName "MCM"
AuthUserFile /etc/modclusterpassword
Require user admin
</Location>

Mais sobre segurança em: https://developer.jboss.org/thread/258299


Perfomance
- Com Java 8 já vai aumentar muuuito a performance comparado com versões anteriores..
- o load balancer é bom para performance pois vai distribuir os acessos deixando tudo mais rápido...
- gzip compression no Apache é essencial
- Configure xms e xmx...
- faça testes de desempenho e utilize ferramentas de monitoramento: http://localhost8080.blogspot.com.br/2016/07/monitorar-ambiente-infra-e-jboss-wildfly.html
- Tuning: http://localhost8080.blogspot.com.br/2014/06/tunning-de-aplicacoes-java.html


Integração contínua
Use! :)


Consultoria:
Lembrando que se precisar dou consultorias nesse assunto e também em questões como performance, arquitetura, integração contínua, montagem de ambientes com load balancer e cluster, etc... Só entrar em contato: adriano@localhost8080.com.br


Abraço!
Adriano Schmidt

domingo, 21 de fevereiro de 2016

handshake_failure paypal

Opa :D

Rodando meu client Java para obter o token do paypal, obtive o seguinte erro:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLSocketImpl.recvAlert(Unknown Source)
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
at snippet.PaypalToken.main(PaypalToken.java:31)

Pra resolver, é necessário passar esse parâmetro pra JVM:
-Dhttps.protocols=TLSv1.1,TLSv1.2

No eclipse, vai em "Run configurations"


Acessa a aba "Arguments"

Em VM Arguments, coloque "-Dhttps.protocols=TLSv1.1,TLSv1.2" sem as aspas

Pronto, ao rodar novamente funcionará

Fonte: http://stackoverflow.com/questions/34963083/paypal-sandbox-api-javax-net-ssl-sslhandshakeexception-received-fatal-alert-h

Abraço!!
Adriano Schmidt

domingo, 27 de setembro de 2015

JavaScript no ServerSide com WildFly 10

Fala galera... fiz uns exemplos aqui pra testar a nova funcionalidade do WildFly 10 que permite que a gente escreva código JavaScript no Server Side \o) Criei alguns RESTs, um deles inclusive acessa um banco de dados e retorna o JSON....

Segue abaixo o código (github) e o passo-a-passo pra rodar aí na sua máquina.

Pré-requisitos:
- Java 8 instalado;
- Maven instalado;

Siga esses passos:
- Baixar e descompactar o WildFly 10
- Ir na pasta bin do WildFly e rodar o standalone.bat (no Windows) ou standalone.sh (no linux)
- Baixar esse projeto do github: https://github.com/adrianoschmidt/wildfly-js
- Abrir a pasta do projeto e rodar um "mvn clean install"
- Copiar o war gerado na pasta target do projeto e colar no <WildFly>/standalone/deployments
- Acessar via browser as seguintes URLs:

http://localhost:8080/wildfly-js/hello




http://localhost:8080/wildfly-js/hello/json




https://localhost:8080/wildfly-js/rest/members




Nesse post tem mais detalhes: http://wildfly.org/news/2015/08/10/Javascript-Support-In-Wildfly/

Abraço!!
Adriano Schmidt

Testar acesso JMX no WildFly

Fala pessoal,

Fiz uma classe Java para se comunicar com o JMX Client de um WildFly...

O fonte está no meu github:
https://github.com/adrianoschmidt/wildfly-jmx-client

Você pode usar isso caso precise mesmo acessar um JMX ou caso queira testar se ele está aberto ou não, esse foi meu caso. Em ambientes de produção é sempre interessante que ele não esteja visível.

Para usar a classe é só rodar ela normalmente pela IDE ou por linha de comando.

Repare nessas duas linhas:
String host = "localhost";
// String host = "192.168.0.35";

Com localhost, ao rodar na máquina onde está o WildFly deveria funcionar, pelo IP não deveria funcionar, pois por segurança não deveria estar disponível para acesso externo.

Para bloquear o acesso você pode fazer isso na sua infraestrutura ou no WildFly no stanalone.xml na seção interfaces.

Qualquer dúvida é só avisar!
Adriano Schmidt

segunda-feira, 27 de julho de 2015

Como trocar versão do Java no ubuntu?

Olá :)

No terminal, rode o comando "java -version" para ver a versão atual utilizada na sua máquina:







Rode o "sudo update-alternatives --config java" para ver as versões instaladas na sua máquina.
Como você usou o "sudo" talvez seja solicitado a senha do seu usuário.
Depois digite o número da coluna "Selection" de acordo com a versão que você que utilizar.















Depois rode o "java -version" de novo para verificar se funcionou:







É isso :)

Abraço!
Adriano Schmidt

terça-feira, 21 de julho de 2015

Spring OAP

Hoje precisei criar um interceptor.

Queria que antes e depois da execução de determinados métodos fosse chamado um Rest.
Também queria que se o método lançasse uma exception, chamasse outro Rest.

Pensei em annotation processor... orientação a aspectos com o aspectj... no fim resolvi com o Spring AOP.

Resumindo, você precisa:

Criar uma annotation para anotar no método que você quer interceptar.
Criar um Advisor para ler os métodos que tem a annotation.
Criar o interceptador para inserir o comportamento que você quer.
Alterar o applicationContext.xml e colocar o component-scan com o pacote onde está seu Advisor e adicionar o bean DefaultAdvisorAutoProxyCreator.

Com isso você consegue apenas colocando uma anotação no seu método fazer algo antes dele ser chamado, depois, ou tratar exceptions por exemplo.

Você pode ver o código nesse meu projeto no GitHub: https://github.com/adrianoschmidt/springaop

Mais detalhes em:
http://blog.javaforge.net/post/76125490725/spring-aop-method-interceptor-annotation

Abraço!!
Adriano Schmidt

sexta-feira, 8 de maio de 2015

Selenium Scrool

Olá pessoal,

Estou trabalhando com Selenium e precisei faz um scrool na página para ir para o fim dela.

Fiz da seguinte forma:

/**
* Faz scrool para o fim da pagina 
*/
public void scroolToBottom() {
    String command = "scrollTo(0,3000)";

    JavascriptExecutor javascriptExecutor = (JavascriptExecutor) webDriver;
    javascriptExecutor.executeScript(command);

    try {
        Thread.sleep(5000L);
    } catch (InterruptedException e) {
        logger.error(e);
    }
}

Não sei se é a melhor forma, mas funcionou, vou avaliar outras possibilidade aqui e qualquer coisa atualizo esse post.

Abraço!
Adriano Schmidt

sexta-feira, 6 de março de 2015

Sizelimit Exceeded OpenLDAP

See the English Version

Fala galera!

Hoje eu tive esse problema em um projeto Java quando eu tentei fazer uma pesquina no OpenLDAP:
2015-02-26 16:44:04,875 ERROR [br.com.localhost8080.ldap.MyClass] Sizelimit Exceeded
LDAPException: Sizelimit Exceeded (4) Sizelimit Exceeded

LDAPException: Matched DN:
at com.novell.ldap.LDAPResponse.getResultException(Unknown Source)
at com.novell.ldap.LDAPResponse.chkResultCode(Unknown Source)
at com.novell.ldap.LDAPSearchResults.next(Unknown Source)
at br.com.localhost8080.ldap.LdapSynchronizer.synchronize(LdapSynchronizer.java:84)

Isso aconteceu porque o meu OpenLDAP tinha 1500 users... e o sizelimit default no meu Java Client era 1000.

Alterando o parametro sizelimit no slapd.conf no OpenLDAP não resolveu o problema.

Para resolver eu usei a classe com.novell.ldap.LDAPSearchConstraints dessa forma:
LDAPSearchConstraints ldsc = new LDAPSearchConstraints();
ldsc.setMaxResults(0);

connection.search(searchBase, searchScope, searchFilter, new String[] {}, false, ldsc);
Setnado o MaxResults com 0 (zero) o sizelimit fica ilimitado.

Abraços!
Adriano Schmidt

sexta-feira, 27 de fevereiro de 2015

Sizelimit Exceeded OpenLDAP

Veja a versão em português

Hello my friends,

Today I had this problem in my Java project when I tried do a search in OpenLDAP:
2015-02-26 16:44:04,875 ERROR [br.com.localhost8080.ldap.MyClass] Sizelimit Exceeded
LDAPException: Sizelimit Exceeded (4) Sizelimit Exceeded

LDAPException: Matched DN:
at com.novell.ldap.LDAPResponse.getResultException(Unknown Source)
at com.novell.ldap.LDAPResponse.chkResultCode(Unknown Source)
at com.novell.ldap.LDAPSearchResults.next(Unknown Source)
at br.com.localhost8080.ldap.LdapSynchronizer.synchronize(LdapSynchronizer.java:84)

It happens because the OpenLDAP had 1500 users... and the default sizelimit in my Java client was 1000.

Changing the parameter sizelimit at slapd.conf in OpenLDAP doesn't solve the problem.

To solve this I used the class com.novell.ldap.LDAPSearchConstraints like this:
LDAPSearchConstraints ldsc = new LDAPSearchConstraints();
ldsc.setMaxResults(0);

connection.search(searchBase, searchScope, searchFilter, new String[] {}, false, ldsc);
Setting the MaxResults with 0 (zero) the sizelimit becomes unlimited.

Best Regards,
Adriano Schmidt

quinta-feira, 12 de fevereiro de 2015

Como saber qual é o JSP em um projeto Struts?

Estou mexendo em um projeto bem antigo e precisei encontrar os arquivos JSP de cada tela que eu abria.

A partir da URL abaixo vamos descobrir o JSP

http://localhost:8080/meuprojeto/usuario.do?action=listarUsuarios

Primeiro vá no UsuarioAction (por causa do usuario.do)
Nesta classe, vá no método listarUsuarios (por causa da action)
Veja o que esse método retorna (por exemplo: return "listar";)

public ActionForward listarUsuarios(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
[...]
return mapping.findForward("listar");
}

Vá no struts-config.xml
Procure por UsuarioAction
Logo abaixo procure por "listar" (retorno do método)
Na linha do "listar" vai dizer qual é o jsp

<action path="/usuario" type="br.com.localhost8080.struts.UsuarioAction" name="usuarioForm" scope="request" parameter="action">
<forward name="listar" path="/p_listar_usuarios.jsp" />

Qualquer coisa dá um Ctrl+H com algum texto da tela :D

Att,
Adriano Schmidt

sexta-feira, 6 de fevereiro de 2015

Java InputStream e Encoding

Pessoal... ao ler um arquivo no Java todos os caracteres especiais (letras com acento por exemplo) ficaram desconfigurados. Ficaram assim: �

Quando eu executava no Windows funcionava perfeitamente, mas no linux ficava desconfigurado.

Isso acontecia pois eu estava lendo o arquivo dessa forma:

InputStream myInputStream = MySampleClass.class.getResourceAsStream("./MyI18nFile.properties");
List lines = org.apache.commons.io.IOUtils.readLines(myInputStream);

Para resolver tive que usar um InputStreamReader setando o encoding(charset), pois não consegui setar o encoding direto no InputStream.
Uma explicação para isso é que InputStream lê blocos de bytes, já o InputStreamReader lê blocos de chars. Não sei se é isso mesmo.

O fonte ficou assim:

InputStream myInputStream = MySampleClass.class.getResourceAsStream("./MyI18nFile.properties");
InputStreamReader myInputStreamReader = new InputStreamReader(myInputStream, Charset.forName("ISO-8859-1"));
List lines = org.apache.commons.io.IOUtils.readLines(myInputStreamReader);

Vejam que eu usei Charset.forName("ISO-8859-1"), fiz isso pois meus arquivos foram criados no windows, mas o java foi executado no linux. Se no seu caso for o contrário, talvez você tenha que usar Charset.forName("UTF-8")

Fonte: http://stackoverflow.com/questions/19317606/java-substring-broken-encoding

Abraço!!
Adriano Schmidt

quinta-feira, 5 de fevereiro de 2015

BDD Cucumber Java DDD DSL

Hoje resolvi estudar a teoria de BDD, DDD, DSL, estudar cucumber, cucumber para Java... etc...

Comecei estudando um pouco de DSL, que é uma forma de você escrever em altíssimo nível negócio e código quase que ao mesmo tempo.
Ao invés de escrever o método que soma dois valores com a sintaxe de alguma linguagem de programação você vai escrever que será necessário somar dois valores.

Depois ao estudar Cucumber (Ferramenta para BDD) vi que ela usava DSL, na verdade usa Gherkin, que é uma linguagem de DSL.

Não tive tempo de finalizar esse artigo.. logo faço isso.. mas seguem alguns links que podem ser úteis:

DSL:
http://martinfowler.com/books/dsl.html

Cucumber:
http://cukes.info/

Gherkin:
https://github.com/cucumber/cucumber/wiki/Gherkin

The Cucumber Book (PDF)
https://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0CB0QFjAA&url=https%3A%2F%2Fwiki.kuali.org%2Fdownload%2Fattachments%2F329384409%2FThe%2520Cucumber%2520Book.pdf%3Fversion%3D1%26modificationDate%3D1407504510000%26api%3Dv2&ei=7nnRVIX9IcHAggTE_YD4BA&usg=AFQjCNEwixnbrWYSEM1teUwGcUIZDO8_0g&sig2=dWa9zlqday0XrVCqP-N2Kg&bvm=bv.85076809,d.eXY


Outros links:
http://fit.c2.com/wiki.cgi?IntroductionToFit
http://www.bugbang.com.br/entendendo-bdd-com-cucumber-parte-i/
http://martinfowler.com/bliki/UbiquitousLanguage.html
http://behaviourdriven.org/
https://github.com/cucumber/cucumber/wiki
https://groups.google.com/forum/#!forum/cukes
https://pragprog.com/book/srjcuc/the-cucumber-for-java-book

terça-feira, 16 de dezembro de 2014

Failure executing javac

Hoje tive o erro abaixo ao executar um "mvn install"

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2:compile (default-compile) on project avmais: Compilation failure
[ERROR] Failure executing javac, but could not parse the error:
[ERROR] O sistema nÆo pode encontrar o caminho especificado.

Estava tudo certinho nas minhas variáveis de ambiente e configurações do projeto...

Depois de muita luta vi que o erro foi causado pois no meu pom.xml tinha a seguinte linha:
<maven .compiler.executable="">${env.OPENSHIFT_WILDFLY_DIR}usr/lib/jvm/jdk1.8.0_05/bin/javac</maven>

Após remover essa linha funcionou local.

Abraço!
Adriano Schmidt

segunda-feira, 10 de novembro de 2014

InternetAccessValidator

Hoje a internet caiu aqui na minha casa...

Eu estava testando se voltava de 5 em 5 minutos... então resolvi fazer um programa Java que fizesse isso pra mim.

Ele verifica se o computador tem acesso à internet. Caso não tenha, tenta novamente após 10 segundos até ter acesso, e quando tiver, fará o computador dar 5 beeps.

Interessante para aprender a executar comandos no sistema operacional e aprender a fazer um beep.

Segue fonte: https://github.com/adrianoschmidt/InternetAccessValidator/blob/master/src/br/com/localhost8080/iav/InternetAccessValidator.java

Abraços!
Adriano Schmidt

quinta-feira, 7 de agosto de 2014

Change JBoss Locale

Versão em português

Hello,

Today I had problems with numeric fields and dates. I typed 20,00 and was displayed 2000. I also had problems with the display of dates.

The problem didn't happen in de development machines, just in homologation machines, because the default locale was different in this environments.

In your eclipse:
- Go to in "Server
- Double-click at JBoss
- Click in "Open Launch Configuration"
- Type at the end of "VM Arguments" field: -Duser.language=pt -Duser.country=BR

But to start JBoss with command line, it doesn't work:
standalone.bat -Duser.language=pt -Duser.country=BR

You need to change the configuration files.

In Windows environments, you must add the following line in the file standalone.conf.bat
set "JAVA_OPTS=%JAVA_OPTS% -Duser.language=pt -Duser.country=BR"

In Linux environments, you must add the following line in the file standalone.conf
JAVA_OPTS="$JAVA_OPTS -Duser.language=pt -Duser.country=BR"

Best Regards!
Adriano Schmidt

PS: My English isn't very good, if you see something wrong please let me know.

Mudar Locale do JBoss

English version

Olá,

Hoje tive problemas com campos numéricos e com datas. Eu digitava 20,00 e ele virava 2000 e outras loucuras assim pois trocava vírgula com ponto e vice-versa, também alguns campos de data estavam aparecendo Feb, 08, 2014 e não 08/02/2014.

Nas máquinas dos desenvolvedores não acontecia isto, porém, no ambiente de homologação acontecia. Os desenvolvedores tinham máquina cujo Locale default era pt_BR (português do Brasil) já no servidor era en_US (inglês dos Estados Unidos).

O ideal é você tratar isso na sua aplicação, porém, pode ser resolvido mudando o locale do JBoss.

No eclipse é só você ir na aba servers, dar dois cliques no seu JBoss, clicar em "Open Launch Configuration" e adicionar os seguintes parâmetros em VM Arguments:
-Duser.language=pt -Duser.country=BR

Já quando você for iniciar via linha de comando NÃO pode simplesmente adicionar dessa forma:
standalone.bat -Duser.language=pt -Duser.country=BR

Dessa forma não funciona, é preciso alterar os arquivos de configuração:

Em ambiente windows precisa alterar o arquivo standalone.conf.bat adicionando a linha abaixo após as outras linhas semelhantes a ela:
set "JAVA_OPTS=%JAVA_OPTS% -Duser.language=pt -Duser.country=BR"

Em ambiente linux precisa alterar o arquivo standalone.conf adicionando a linha abaixo ao final do arquivo:
JAVA_OPTS="$JAVA_OPTS -Duser.language=pt -Duser.country=BR"

Abraço!
Adriano Schmidt

quinta-feira, 10 de julho de 2014

Join HQL

Quando no Java temos uma Entidade que tem uma lista de outra entidade.
E vamos fazer uma consulta com HQL (Hibernate Query Language) e precisamos acessar um atributo de um item da lista precisamos fazer um JOIN.

Segue um exemplo bem básico de como podemos fazer:

select a from TabelaA a inner join a.bList b inner join b.c.dList d where d.id = :id"

select a from TabelaA a, in (a.bList) b, in (b.c.dList) d where d.id = :id

Abraço!
Adriano Schmidt

sexta-feira, 4 de julho de 2014

Boas práticas - Rest

Pessoal...

Estou trabalhando com alguns projetos utilizando Rest. Montei esse e-mail para enviar à equipe de desenvolvimento e resolvi publicar aqui também.

A ideia é utilizar o conceito de RESTful utilizando as melhores práticas de desenvolvimento. Darei algumas dicas simples que podemos seguir:

1) Não usar verbos nos paths dos Rests:

Você não pode ter um localhost:8080/myapp/rest/deletarProduto e dar um HTTP GET nele.

Tem que ser um localhost:8080/myapp/rest/produto e você dá um HTTP DELETE nele



Tem alguns casos especiais (somarValores, checarSeEmailTemFormatoValido ou algoasism...) que são um pouquinho diferentes.. em outra oportunidade falarei mais sobre isso..


2) Passagem de parâmetros através de queryString do método GET

<URL>?parametro1=valor1&parametro2=valor2

Isso deve ser usado para filtros no HTTP GET de localhost:8080/myapp/rest/produto?apenasAtivos=true

Na implementação, basta utilizar @QueryParam ao invés de @PathParam


3) Sempre retornar um Response (javax.ws.rs.core.Response;)

Nunca retorne uma coleção de entidades ou uma string diretamente... encapsule em um Response para poder passar o HTTP Status adequadamente.

return Response.ok(banners).build();
ou outro Status:
return Response.status(Status.FORBIDDEN).build();


4) Sempre retornar JSON de forma automática:
Basta adicionar a linha abaixo acima do método no Rest:
@Produces(MediaType.APPLICATION_JSON)

Não faça a conversão de objetos para JSON na mão.


5) Atualização parcial:
Existem casos onde você não quer atualizar um registro inteiro, e sim apenas uma propriedade dele, atualizar um status por exemplo.

O @PUT é pra atualização, mas ele é pra atualizar o objeto inteiro.

Para isso existe o @PATCH, mas não sei se ele é padrão, se todos os servidores de aplicação tem.

Uma outra ideia é fazer vários @PUT, fica bacana também:

PUT localhost:8080/myapp/rest/livro/{id}/propriedadeX
PUT localhost:8080/myapp/rest/livro/{id}/propriedadeY

Outra ideia é ter um @PUT pra atualizar o objeto inteiro e um @PUT que recebe um Map com os atributos a serem atualizados e seus novos valores.


6) Não implemente todos os métodos
Não é necessário implementar todos os métodos se eles não serão usados. Por exemplo, se é um objeto só vai ter um @GET não é necessário implementar o @POST, o @PUT e o @DELETE.

No máximo faça o método no Rest que retorna um status de erro informando que não foi implementado.


Mais:
Mais detalhes e para quem quiser estudar mais sobre Rest recomendo o artigo abaixo:
http://www.devmedia.com.br/construindo-uma-restful-api-parte-1/29904
http://www.devmedia.com.br/restful-api-construindo-uma-api-simples-parte-2/30069

Na Supero (empresa que trabalho) temos conta MVP no devmedia, caso você não tenho recomendo fazer, é um investimento muito válido!

Abraços!
Adriano Schmidt

quarta-feira, 25 de junho de 2014

Tunning de aplicações Java

Pessoal.. vou postar aqui alguns itens que sempre recomendo para melhorar o desempenho de uma aplicação Java.

Fazer testes de desempenho ou analisar as aplicações com JMeter, NewRelic, VisualVM, jConsole é o mundo ideal! Através disso é possível identificar os gargalos da aplicação! Os pontos que mais utilizam recursos computacionais como memória e processador por exemplo.

Configurar adequadamente a memória utilizada.. ou seja, estude xms, xmx, maxpermgen..
Uma dica é sempre colocar o xms e o xmx igual em ambiente de produção. E o ideal não é simplesmente colocar o valor mais alto possível, é preciso analisar qual é o valor ideal, e isso é descoberto através de testes e monitoramento, ou através do feeling e analisando com o tempo como a aplicação se comporta.

Recomendo utilizar a JRockit como JVM. Ela é mantida pela Oracle também e tem um gerenciamento de memória muito melhor que das outras JVMs, o garbage collector funciona bem melhor.
Mas só tem pra Java 6, mas em todos os clientes que atuo, sempre que possível, implanto a JRockit, é notável o ganho obtido no uso de recursos computacionais como memória.

Dá pra fazer tunning também de acordo com a tecnologia que você está usando.. JSF... JMS... pool de EJB... Banco de dados...

Dá pra monitorar a aplicação pelo jenkins também, fazer um job que checa a memória e qualquer avisa a equipe de infra ou até reinicia, dá pra usar o nagios...

Etc... Existem milhões de outras coisas que podem ser feitas, mas como escrevi esse texto para ajudar um amigo, resolvi postá-lo aqui para talvez ajudar outras pessoas também.

Abraços!
Adriano Schmidt

segunda-feira, 16 de junho de 2014

Cuidados ao entrar num projeto novo

Pessoal... queria dar algumas dicas para quando você for entrar um projeto novo...

1) Ctrl+Shift+F
Nunca dê um Ctrl+Shift+F no projeto inteiro.. nem na classe que você está alterando...

Um Ctrl+Shift+F atrapalha muito a realização de merges e de certa forma faz você perder o histórico de alterações no controle de versão, pois vai ser difícil comparar algo com uma versão antiga pois vai estar com uma formatação toda diferente.

Se você está criando uma classe nova, tudo bem, mas muito cuidado ao mexer em códigos já existentes.

Caso você crie um método novo, você pode selecionar esse método, e dar um Ctrl+Shif+F, pois vai formatar apenar o trecho de código selecionado, mantendo intacto o resto da classe.

Tem até como criar um xml de formatação no eclipse e depois as outras pessoas podem importar em seus eclipses, mas acho muito trabalhoso manter isso.

Caso seja decidido aplicar algo no projeto inteiro, isso deve ser bem pensado, nunca é só chegar e fazer.

2) Encoding no eclipse
Antes de salvar uma classe verifique se o encoding do projeto no seu eclipse está correto, veja se os acentos não vão virar caracteres estranhos..
Isso é muito comum quando uma equipe usa windows e entra alguém que usa linux ou vice-versa.
Para mudar o encoding do seu projeto no eclipse é só ir nas propriedades do projeto no eclipse.

Caso você ache que o encoding poderia ser outro, converse com a equipe, nunca chegue e mude por conta própria.

3) Encoding no maven
Nunca altere o encoding do projeto no maven colocando no pom a linha abaixo:
UTF-8

Se for fazer isso converse com alguém que já está no projeto ou então você deve saber o que está fazendo.. uma dica é, se for fazer, faça apenas local.

4) Não use acentos em comentários
O título é auto explicativo, a ideia é simples, se não tem acentos, diminui a probabilidade de problemas com encoding. Ah, e sempre é bom falar, em nome de variável também não se deve usar ç ou coisas assim.

Essas simples ações tornam o ambiente de trabalho melhor, faça o bem sem olhar a quem! :D

PS: Escrevi tudo isso e mandei para todos os desenvolvedores da empresa que trabalho depois de passar muitas horas (muitas mesmo) fazendo um merge de um projeto gigante e corrigindo caracteres especiais. Então, não falo por mal, falo para evitar que outras pessoas passem por esse sofrimento.

Abraços!
Adriano Schmidt