domingo, 9 de fevereiro de 2014

Criar Schema Oracle

Pessoal..

Hoje tive que fazer uma atividade simples, criar um schema no oracle, porém era necessário saber a sintaxe, saber um pouco sobre tablespaces e também dar os grants corretos.

Assim sendo, resolvi documentar aqui para caso alguém tenha que fazer algo semelhante:

Segue abaixo uma sugestão de script para criar os databases. Não esqueça de alterar nome_schemad, nome_schema, caminho_sevidor_datafiles:

CREATE TABLESPACE nome_schemad  
DATAFILE ‘caminho_servidor_datafiles\nome_schemad.DBF' SIZE 100M AUTOEXTEND ON
/

CREATE USER nome_schema IDENTIFIED BY nome_schema
DEFAULT TABLESPACE nome_schemad TEMPORARY TABLESPACE TEMP
/
grant connect, resource, create any view, create any synonym, create any table, create database link to nome_schema
/


Ou mais simples ainda usando a TABLESPACE users:

CREATE USER nome_schema IDENTIFIED BY nome_schema
DEFAULT TABLESPACE users TEMPORARY TABLESPACE TEMP
/
grant connect, resource, create any view, create any synonym, create any table, create database link to nome_schema
/

A senha é o que vem depois do IDENTIFIED BY, caso queira pode mudar.

É isso aí, abraços!!
Adriano Schmidt

sexta-feira, 7 de fevereiro de 2014

Marvel Java

Oi pessoal :)

A Marvel lançou o http://developer.marvel.com/ com uma API RESTful para você acessar imagens, histórias, dados entre outras coisas da Marvel.



Você pode usar isso em seu site, em jogos, num app pra celular, num aplicativo pra TV digital ou onde sua criatividade deixar :P

Fiz um client Java só para brincar, chamei ele de JMarvelRestClient, caso queiram executar aí é só criar um projeto java, um pacote br.com.localhost8080.test e colar a classe abaixo e alterar para usar suas próprias chaves no método mountUrlRest!!! Para obter as chaves é só se cadastrar lá no http://developer.marvel.com/

Nessa classe tem o client Rest e tem um método para converter uma string para MD5 para a autenticação.

A saída da execução desta classe está lá no final deste artigo. Até lá :P

package br.com.localhost8080.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

/**
 * Java Client for the Marvel Rest API
 */
public class JMarvelRestClient {

 /**
  * Call a Rest from Marvel just for test
  */
 public static void main(String[] args) {
  HttpURLConnection conn = null;
  try {
   URL url = new URL(JMarvelRestClient.mountRestUrl());

   conn = (HttpURLConnection) url.openConnection();
   conn.setRequestMethod("GET");
   conn.setRequestProperty("Accept", "application/json");

   if (conn.getResponseCode() != 200) {
    throw new RuntimeException("Failed: HTTP error code: " + conn.getResponseCode());
   }

   BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));

   String output = null;
   String retornoRest = "";
   while ((output = br.readLine()) != null) {
    retornoRest += output;
   }
   System.out.println("\nRest Return: " + retornoRest);

   JMarvelRestClient.mountImageUrl(retornoRest);
  } catch (MalformedURLException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  } finally {
   conn.disconnect();
  }

 }

 /**
  * Mount the URL with keys and hash
  */
 private static String mountRestUrl() {
  Long timeStamp = new Date().getTime();
  String privateKey = "PUT_HERE_YOUR_PRIVATE_KEY";
  String apikey = "PUT_HERE_YOUR_PUBLIC_KEY";
  String hash = JMarvelRestClient.generateHash(timeStamp + privateKey + apikey);

  String urlCompleta = "http://gateway.marvel.com/v1/public/comics/12?ts=" + timeStamp + "&apikey=" + apikey + "&hash=" + hash;

  System.out.println("Rest URL: " + urlCompleta);

  return urlCompleta;
 }

 /**
  * Makes a magic that transforms your string in MD5 hash
  */
 private static String generateHash(String string) {
  MessageDigest md = null;
  try {
   md = MessageDigest.getInstance("MD5");
  } catch (NoSuchAlgorithmException e) {
   e.printStackTrace();
  }
  md.update(string.getBytes());
  byte[] bytes = md.digest();

  StringBuilder s = new StringBuilder();
  for (int i = 0; i < bytes.length; i++) {
   int parteAlta = ((bytes[i] >> 4) & 0xf) << 4;
   int parteBaixa = bytes[i] & 0xf;
   if (parteAlta == 0) {
    s.append('0');
   }
   s.append(Integer.toHexString(parteAlta | parteBaixa));
  }
  return s.toString();
 }

 /**
  * Master workaround to get a JSON attribute, you must do this correctly, I did this because it is more funny :)
  */
 private static void mountImageUrl(String total) {
  int inicio = total.lastIndexOf("\"thumbnail\":{\"path\":\"");
  int fim = total.indexOf("\",\"extension\":\"");
  String ss = total.substring(inicio, fim).substring(21) + "/portrait_xlarge.jpg";

  System.out.println("\nUse this URL to see the image returned by Rest: " + ss);
 }

}
Oi de novo :) Aqui está a saída desse meu código. Usei um [...] pra ficar um pouco menor.
Rest URL: http://gateway.marvel.com/v1/public/comics/12?ts=1391742038152&apikey=0458f299a5570e88176c0cd08be6a592&hash=37d71302dc8fcbb7a67fab5c25dadc71

Rest Return: {"code":200,"status":"Ok","etag":"e41c5cc5be95cd99d46ec56146f1051099c9abb5","data":{"offset":0,"limit":20,"total":1,"count":1,"results":[{"id":12,"digitalId":4089,"title":"Ultimate Spider-Man (2000) #68","issueNumber":68,"variantDescription":"","description":"SUPERSTARS PART 3 Johnny Storm still doesn't have a high school
[...]
Torch","type":"interiorStory"}],"returned":2},"events":{"available":0,"collectionURI":"http://gateway.marvel.com/v1/public/comics/12/events","items":[],"returned":0}}]}}

Use this URL to see the image returned by Rest: http://i.annihil.us/u/prod/marvel/i/mg/f/90/4bc6b6e773bde/portrait_xlarge.jpg
Pelo Rest recebemos uma URL de uma imagem (mais detalhes em http://developer.marvel.com/documentation/images)

Bom, é isso, qualquer dúvida posta aí que tentarei ajudar!

Fontes:
http://www.mkyong.com/webservices/jax-rs/restfull-java-client-with-java-net-url/
http://codare.net/2007/02/02/java-gerando-codigos-hash-md5-sha/

Abraços!
Adriano Schmidt

quinta-feira, 6 de fevereiro de 2014

There is a process already using the admin port 4848

Pessoal, hoje ao startar o GlassFish no linux (RHEL) tive o seguinte erro:

There is a process already using the admin port 4848 -- it probably is another instance of a GlassFish server


E não tinha outro GlassFish na máquina... então verifiquei o iptables (sudo iptables -L) e tava vazio, dei até um (sudo iptables -F)
para limpar tudo por segurança..

Verifiquei o selinux, mas tava desabilitado também...

Para resolver abri o arquivo /etc/hosts (vi /etc/hosts) e adicionei após a primeira linha:

127.0.0.1 NOMEDAMAQUINA

E resolveu meu problema, GlassFish iniciou certinho!

Para saber o nome da máquina é só usar o comando hostname (hostname)

Fonte: http://www.devmedia.com.br/forum/erro-ao-iniciar-o-glassfish-3-no-ubuntu-server-9-04/134959

Abraço pessoal!!!
Adriano Schmidt

sexta-feira, 31 de janeiro de 2014

JBoss JAAS LDAP Tutorial

Pessoal.. tive que configurar um ambiente JBoss EAP6/AS7 + JAAS + LDAP/AD e apanhei bastante pra conseguir, então resolvi fazer um artigo aqui no blog em formato de tutorial pra documentar o passo-a-passo e ajudar quem tiver que fazer o mesmo.

Primeiro eu segui um tutorial e não deu certo: http://middlewaremagic.com/jboss/?p=378

Não sei o motivo ainda, mas não foi de jeito nenhum.

Depois segui o tutorial do Mauricio Magnani e deu tudo certo! http://jbossdivers.wordpress.com/2012/02/12/utilizando-ldap-login-module-no-jboss-as-7-1/

No tutorial do Mauricio ele usou o openldap no linux, eu utilizei o Apache Directory Studio no Windows (tem pra linux e mac também) para criar meu servidor de LDAP/AD. Esse software é baseado no eclipse e falicita muito o trabalho com LDAP/AD, permite criar servidores, criar usuários, adicionar atributos, tudo pela interface gráfica. É lindo : ) Muito fácil de usar!

Na sua empresa/cliente talvez você já tenha um servidor de LDAP/AD, então você teria que usar ele, mas sugiro criar o server na sua máquina para testar, e depois que estiver tudo funcionando, é só apontar para o LDAP/AD da sua empresa/cliente.

* Instale o Apache Directory Studio
Baixe o Apache Directory Studio, instale, e inicie ele.
http://directory.apache.org/studio/downloads.html

* Crie Server LDAP local
Entre na aba "LDAP Servers" (Caso ela não aparece: Window > Show View > LDAP Servers)
Botão direito > New > New Server
Escolha "ApacheDS 2.0.0
Clique em "Finish"
Inicie o servidor

* Conecte-se no server criado
Entre na aba "Connections"
Botão direito > New Connection
Em "Connection Name" coloque "localhost"
Em "Hostname" coloque "localhost"
Em "Port" coloque "10389"
Clique em next
Em "Bind DN ou user" coloque "uid=admin,ou=system"
Em "Bind password" coloque "secret"
Clique em "Check Authentication", tem que funcionar : )
Clique em "Finish"

*Crie um usuário
Entre na aba "LDAP Browser"
DIT > Root DSE > ou=system" > ou=users
Botão direito em "ou=users" > New > New Entry
Clique em "Create entry from strach"
Clique em "Next"
Em "Available object classes" escolha "inetOrgPerson"
Clique em "Next"
Em "RDN", no primeiro campo, coloque "uid"
Em "RDN", no segundo campo, coloque "user1"
Clique em "Next"
Em "cn" coloque "user1"
Em "sn" coloque "user1"
Botão direito > New Attribute
Em "Attribute type" coloque "userPassword"
Clique em "Finish"
Em "Enter New Password" coloque "secret"
Clique em "OK"
Clique em "Finish"

* Crie uma role
Entre na aba "LDAP Browser"
DIT > Root DSE > ou=system" > ou=groups
Botão direito em "ou=groups" > New > New Entry
Clique em "Create entry from strach"
Clique em "Next"
Em "Available object classes" escolha "groupOfNames"
Clique em "Next"
Em "RDN", no primeiro campo, coloque "cn"
Em "RDN", no segundo campo, coloque "General"
Clique em "Next"
No campo que vai aparecer coloque "uid=user1,ou=users,ou=system"
Clique em "OK"
Clique em "Finish"



* Instale o JBoss AS 7.1.1 ou o JBoss EAP 6.2 (Testei nestas duas versões e funcionou, nas demais versão do AS7 e EAP6 deve funcionar também)
Basta baixar o zip e descompactar
A JDK precisa estar configurada no JAVA_HOME e isso precisa estar no PATH
Rode o standalone.bat ou o standalone.sh do JBoss para verificar se está funcionando.

* Configure o standalone.xml
No subsystem de security adicione as seguintes linhas dentro da tag <security-domains>

<security-domain name="ldap_security_domain">
    <authentication>
        <login-module code="LdapExtended" flag="required">
            <!-- Nao alterar -->
            <module-option name="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory"/>

            <!-- Deve ser colocado o IP e porta do LDAP -->
            <module-option name="java.naming.provider.url" value="ldap://localhost:10389"/>

            <!-- Nao alterar -->
            <module-option name="java.naming.security.authentication" value="simple"/>

            <!-- Deve ser colocado o usuário admin e senha -->
            <module-option name="bindDN" value="uid=admin,ou=system"/>
            <module-option name="bindCredential" value="secret"/>

            <!-- Deve ser colocado o diretorio onde estarao os usuarios -->
            <module-option name="baseCtxDN" value="ou=system"/>

            <!-- Deve ser colocado o atributo que representa o login do usuario -->
            <module-option name="baseFilter" value="(uid={0})"/>

            <!-- Deve ser colocado o diretorio onde estara o grupo com todos os usuarios -->
            <module-option name="rolesCtxDN" value="ou=groups,ou=system"/>

            <!-- Deve ser colocado o atributo do grupo que indica quais usuarios pertencem ao grupo -->
            <module-option name="roleFilter" value="(member={1})"/>

            <!-- Nao alterar -->
            <module-option name="roleAttributeID" value="cn"/>
            <module-option name="roleRecursion" value="-1"/>
            <module-option name="throwValidateError" value="true"/>
            <module-option name="searchScope" value="ONELEVEL_SCOPE"/>
        </login-module>
    </authentication>
</security-domain>


No subsystem de logging adicione as seguintes linhas junto com os demais loggers:

<logger category="org.jboss.security">
  <level name="TRACE"/>
</logger>

Isso serve para sair mais logs no server.log para ajudar a identificar problemas, depois que estiver tudo funcionando, altere de TRACE para WARN.

* Configure o seu projeto
No seu projeto em src/main/webapp/WEB-INF crie um arquivo chamado jboss-web.xml com o seguinte conteúdo:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
    <security-domain>java:/jaas/ldap_security_domain</security-domain>
</jboss-web>


No seu projeto em src/main/webapp/WEB-INF crie um arquivo chamado web.xml com o seguinte conteúdo:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
 <display-name>NomeDoProjeto</display-name>

 <!-- JSF -->
 <servlet>
  <servlet-name>Faces Servlet</servlet-name>
  <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>Faces Servlet</servlet-name>
  <url-pattern>*.jsf</url-pattern>
 </servlet-mapping>
 <welcome-file-list>
  <welcome-file>index.jsf</welcome-file>
 </welcome-file-list>

 <!-- Security -->
 <!-- Aqui voce mexe para dar permissoes para diferentes pastas para roles diferentes -->
 <!-- Nesse exemplo eu permito que apenas usuario da role "General" possam acessar /protected/* -->
 <security-constraint>
  <web-resource-collection>
   <web-resource-name>Protected</web-resource-name>
   <url-pattern>/protected/*</url-pattern>
   <http-method>GET</http-method>
   <http-method>POST</http-method>
  </web-resource-collection>
  <auth-constraint>
   <role-name>General</role-name>
  </auth-constraint>
 </security-constraint>

 <login-config>
  <auth-method>FORM</auth-method>
  <realm-name>LDAP</realm-name>
  <form-login-config>
   <form-login-page>/Login.jsf</form-login-page>
   <form-error-page>/Login.jsf?invalidLogin=true</form-error-page>
  </form-login-config>
 </login-config>

 <security-role>
  <role-name>General</role-name>
 </security-role>

</web-app>


No seu projeto em src/main/webapp crie um arquivo chamado index.xhtml com o seguinte conteúdo:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">

 <h:body>
  <h:outputText value="Ola mundo" />
 </h:body>
</html>


No seu projeto em src/main/webapp crie um arquivo chamado Login.xhtml com o seguinte conteúdo:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">

<h:body>
 <form id="formLogin" action="j_security_check" method="post">

  <h:outputText value="LOGIN"/>

  <br/><br/>

  <h:panelGroup rendered="#{param['invalidLogin'] == 'true'}">
   <h:outputText value="Por favor utilize credenciais autorizadas." />
   <br/><br/>
  </h:panelGroup>

  <h:outputText value="Usuario: "/>
  <h:inputText id="j_username" required="true" />

  <br/><br/>
  
  <h:outputText value="Senha: "/>
  <h:inputSecret id="j_password" feedback="false" required="true"/>

  <br/><br/>

  <h:commandButton id="access_button" type="submit" value="Entrar"/>
 </form>
</h:body>
</html>


No seu projeto em src/main/webapp crie uma pasta chamada protected.
No seu projeto em src/main/webapp/protected crie um arquivo chamado ProtectedFile.xhtml com o seguinte conteúdo:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">

 <h:body>
  <h:outputText value="Arquivo protegido." />
 </h:body>
</html>

* Teste
Reinicie o JBoss e faça deploy da sua aplicação.

Acesse http://localhost:8080/nomeDoProjeto/index.jsf e você vai conseguir acessar normalmente.
Acesse http://localhost:8080/nomeDoProjeto/protected/ProtectedFile.jsf e você vai ser redirecionado para a tela Login.jsf
Entre com o usuário user1 com a senha secret e você vai ser direcionado para tela ProtectedFile.jsf


Pronto :D
Funciona que é uma beleza!!
E mais uma vez quero agradecer ao Mauricio Magnani pelo seu blog http://jbossdivers.wordpress.com/ que me ajudou nessa atividade.

Abraços!!
Adriano Schmidt

quinta-feira, 30 de janeiro de 2014

LDAP - Failed to parse: null, disabling recursion: java.lang.NumberFormatException: null

Configurando um Ambiente JBoss 7.1.1-Final com JAAS e LDAP/AD eu tive o erro abaixo:

14:46:42,273 TRACE [org.jboss.security.auth.spi.LdapExtLoginModule] (http-localhost-127.0.0.1-8080-1) Failed to parse: null, disabling recursion: java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:454) [rt.jar:1.7.0_51]
at java.lang.Integer.parseInt(Integer.java:527) [rt.jar:1.7.0_51]
at org.jboss.security.auth.spi.LdapExtLoginModule.createLdapInitContext(LdapExtLoginModule.java:395) [picketbox-4.0.7.Final.jar:4.0.7.Final]
[...]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
at java.lang.Thread.run(Thread.java:744) [rt.jar:1.7.0_51]

Para resolver, bastou adicionar a linha abaixo no login-module do subsystem security no standalone.xml

<module-option name="roleRecursion" value="-1"/>

Isso resolveu o problema!!!

Abraços!!
Adriano Schmidt

terça-feira, 10 de dezembro de 2013

Instalar GlassFish 3.1.2.2 (build 5) - Final

Pessoal..

Tive que instalar um GlassFish em um cliente.. por mais que seja uma operação simples vou documentar aqui o passo-a-passo.

* Verifique se existe o JDK está instalado na máquina (Caso não esteja, você vai precisar instalar)
$java -version

* Baixe o zip do GlassFish (Existem os instaladores .exe e .sh, mas eu sempre prefiro os zip's)
https://glassfish.java.net/downloads/3.1.2.2-final.html

* Descompacte o zip na pasta desejada. Se for linux pode ser algo assim:
$cd /home
$mkdir glassfish-3.1.2.2
$cd glassfish-3.1.2.2
[então você copia para essa pasta o zip]
$unzip glassfish-3.1.2.2.zip

* Agora é só startar, para isso basta executar os seguintes comandos:
$cd /home/glassfish-3.1.2.2/glassfish3/glassfish/bin/
$nohup ./startserv &
$[ctrl + c]

* Para parar o GlassFish basta executar os seguintes comandos:
$cd /home/glassfish-3.1.2.2/glassfish3/glassfish/bin/
$./stopserv

* Para acessar é só utilizar estas URLs:
Home: http://[IP DA MÁQUINA]:8080/
Admin: http://[IP DA MÁQUINA]:4848/

* O ideal é startar através de um serviço ou algo do gênero para ser mais fácil para os administradores do ambiente.

* Outra coisa, recomendo NUNCA startarem o GlassFish com o usuário root. Pois através de uma aplicação Java, com poucas linhas de código, caso o servidor de aplicação tenha sido startado com root, é possível acessar e alterar o disco, entre outras atividades não desejáveis.

* Para liberar acesso ao console administrativo por outras máquinas é necessário realizar os seguintes comandos:
$./asadmin --port 4848 change-admin-password
Enter admin user name [default: admin]> [Apenas aperte enter]
Enter admin password> [Apenas aperte enter]
Enter new admin password> [Digite a senha para o admin]
Enter new admin password again> [Digite a senha para o admin]
Command change-admin-password executed successfully.

$./asadmin --host [IP DESSA MÁQUINA] --port 4848 enable-secure-admin

Bom, é isso galera. Precisando podem comentar aqui no post que eu tentarei ajudar.

Abraços!
Adriano Schmidt

segunda-feira, 25 de novembro de 2013

Tuning EJB Pool JBoss 7

Pessoal..

Hoje eu tive o erro: "JBAS014516: Falha ao adquirir uma permissão com 5 MINUTES".

Isso aconteceu pois estourou o pool de EJBs..

Basicamente ele funciona assim... tem 20 instâncias no pool..

Cada vez que uma pessoa está usando o sistema e aperta em um botão ou entra em uma tela que chama um serviço EJB, uma instância é tirada do pool..

Se 20 pessoas fizerem isso ao mesmo tempo, acessando o mesmo serviço, as 20 instâncias estarão ocupadas, então se uma 21ª pessoa precisar chamar o serviço EJB, ela vai ter que esperar alguma instância parar de ser utilizada e voltar ao pool... se isso levar mais de 5 minutos, acontece o erro do log: "JBAS014516: Falha ao adquirir uma permissão com 5 MINUTES".

Se tiver 50 pessoas acessando ao mesmo tempo, a 50ª terá que esperar 30 instâncias serem liberadas.

Esse valor de 20 instâncias e o tempo de timeout são configuráveis.

No caso de um sistema, ou de um jboss que tenha vários sistemas, que tenha muitos usuários simultâneos é interessante aumentar o pool de EJBs.

Para saber o melhor valor existem três alternativas:
1) Deve ser feito monitoramento do pool através do JBoss CLI ou de algum profiler que tenha essa funcionalidade
2) Testes de desempenho com JMeter (ou outra ferramenta) e avaliar o desempenho da aplicação com diferentes valores de pool.
3) Seguir o feeling e aumentar de 20 para 30 ou 40 e ir sentindo como a aplicação se comporta com o tempo.

Para alterar os valores do pool você pode fazer isso:
- Direto no standalone.xml ou domain.xml
- No Web Console
- Via JBoss CLI

Infelizmente apenas conseguimos definir o pool para o subsystem inteiro, não conseguimos definir por aplicação ou até mesmo por Serviço EJB.

Existem 3 pool que podem ser alterados:
- slsb-strict-max-pool > é utilizado pelos stateless service bean (foi esse que causou meu erro)
- mdb-strict-max-pool > MDB, utilizado por serviços JMS
- thread-pools > é usado pelo EJB Timer, pelo Asynchronous EJB e para fazer chamadas de EJB remotos.. Caso você use estas funcionalidades e sinta necessidade, esse pool pode ser alterado também. Nesse caso você pode até criar pools separados pois estas 3 funcionalidades compartilham o mesmo pool.

Mais detalhes sobre o subsystem EJB: https://docs.jboss.org/author/display/AS71/EJB3+subsystem+configuration+guide

É isso aí : ) abraço!
Adriano Schmidt

terça-feira, 27 de agosto de 2013

Error loading theme, cannot find "theme.css" resource of "primefaces-bootstrap" library

Pessoal.. hoje tive o erro:

[8/27/13 15:17:23:188 BRT] 00000043 CustomExcepti E   Error loading theme, cannot find "theme.css" resource of "primefaces-bootstrap" library
                                 javax.faces.FacesException: Error loading theme, cannot find "theme.css" resource of "primefaces-bootstrap" library
    at org.primefaces.renderkit.HeadRenderer.encodeTheme(HeadRenderer.java:130)
    at org.primefaces.renderkit.HeadRenderer.encodeBegin(HeadRenderer.java:92)
    at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:579)
    at javax.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:519)
    at javax.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:533)
    at org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(FaceletViewDeclarationLanguage.java:1581)
    at org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:264)
    at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:116)
    at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:239)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:191)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1224)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:774)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:456)
    at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:178)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.invokeTarget(WebAppFilterChain.java:136)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:97)
    at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:79)
    at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:195)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:91)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:928)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1025)
    at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:87)
    at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:895)
    at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1662)
    at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:195)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:452)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:511)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:305)
    at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:83)
    at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
    at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
    at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
    at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
    at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
    at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
    at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1659)

[8/27/13 15:17:23:188 BRT] 00000043 SystemOut     O
 DEBUG ERROR
[8/27/13 15:17:23:188 BRT] 00000043 SystemOut     O


O erro foi pois eu tinha isso no meu web.xml:

    <context-param>
        <param-name>primefaces.THEME</param-name>
        <param-value>bootstrap</param-value>
    </context-param>

porém eu não tinha a dependência no meu pom.xml para o primefaces-bootstrap.. por isso acontecia o erro..

Abraços!
Adriano Schmidt

sexta-feira, 2 de agosto de 2013

Buscar cidade pelo IP

Oi pessoal : )

Hoje tive que, pelo IP, descobrir a cidade do usuário.

Estou fazendo este post para repassar minhas descobertas : )

Antes de mais nada, caso você queira saber o seu IP é só acessar: http://www.whatismyip.com/

FreeGeoIP


Resumindo (e correndo o risco de que você não termine de ler este post) o jeito mais simples é esse:

http://freegeoip.net/json/170.130.90.30

Esse serviço Rest é free e retorna em JSON a cidade e outras informações pelo IP. Você pode acessá-lo diretamente pelo browser ou via programação fazendo uma chamada Rest.

Essa busca é feita com base em um banco de dados gigante que é atualizado diariamente. Ele não é 100% preciso mas ajuda bastante!

Existe a possibilidade de que o retorno seja XML, CSV.

Mais detalhes e limitações em: http://freegeoip.net/

O freegeoip utiliza um banco de dados free da MaxMind

MaxMind


Você pode utilizar diretamente o serviço rest da MaxMinds, ela tem 2 modelos de serviço:

Free: Tem um número limitado de consultas e você tem que botar um link para o site da MaxMind no seu site
Pago: Mais precisão e garantia que o serviço estará no ar.. são 20 dólares para 50.000 consultas, tem outros planos também.

Mais detalhes e limitações em: http://www.maxmind.com/pt/geolocation_landing

API de GeoLocation do HTML5


Outra possibilidade é usar a API de GeoLocation do HTML5:

http://www.w3schools.com/html/html5_geolocation.asp

Aí você consegue pegar latitude e longitude aproximada da pessoa, e com isso pode buscar a cidade.

Existe uma diferença, talvez desvantagem, em fazer dessa forma é que o usuário terá que autorizar o sistema a utilizar sua localização. Aparecerá uma janela com a mensagem "Deseja compartilhar sua localização com este site?"

Enfim, a busca pela cidade por lat e lng pode ser feita de duas formas:

Serviço Google:
Procure por Geocodificação reversa (busca de endereços) em: https://developers.google.com/maps/documentation/geocoding/?hl=pt-br

Observação: a Google Geocoding API só pode ser usada junto com um mapa do Google; é proibido usar os resultados da geocodificação sem exibi-los em um mapa

Banco de dados próprio
É possível buscar em um banco de dados ou arquivo de cidades com suas respectivas latitudes e longitudes.. aí é só você fazer um algoritmo simples de aproximação.

Esse site tem uma lista das maiores cidades do Brasil com lat e lng: http://www.mapsofworld.com/lat_long/brazil-lat-long.html

Você também pode pegar essa lista direto do IBGE, procure no google por Cidades_do_Brasil_2008.rar que você via achar.

Direto pelo browser

Sem API, mas forma rápida e free:

https://pt.vpnmentor.com/ferramentas/ipinfo/

Abraaço!!!
Adriano Schmidt

PS: Agradeço ao Rafael dos Santos que fez esta pesquisa comigo!

terça-feira, 2 de julho de 2013

JBoss AS 7 - Cluster SSO

Oi pessoal : )

Eu montei um ambiente com vários JBoss AS 7 em cluster, a replicação de sessão estava funcionando perfeitamente, porém, o user principal (usuário logado) não estava replicando para os outros nós do cluster.

Achei na documentação que para isso funcionar precisavam ser feitas mais alguns ajustes:

https://access.redhat.com/site/documentation/en-US/JBoss_Enterprise_Application_Platform/6.1/html/Development_Guide/Use_Single_Sign_On_SSO_In_A_Web_Application.html

mas seguindo a documentação não funcionou :(

os pré-requisitos são os mesmos.. existem apenas duas coisas erradas na documentação:

1) cache-container="web"
O script abaixo está errado:
/profile=ha/subsystem=web/virtual-server=default-host/sso=configuration:add(cache-container="web",cache-name="sso",reauthenticate="false",domain="domain.com")

o correto é:
/profile=ha/subsystem=web/virtual-server=default-host/sso=configuration:add(cache-container="web")

(Lembrando que você deve alterar o nome do perfil para o perfil que você está utilizando, e caso você esteja no standalone deve retirar o /profile=ha do comando)

2) Valve
Você não deve adicionar nenhum valve no seu jboss-web.xml pois a classe ClusteredSingleSignOn é instanciada automaticamente.

Pronto! Funcionou perfeitamente!

Fonte: https://community.jboss.org/message/825375#825375

Abraços!
Adriano Schmidt